/*
	This file is part of Vajolet.

    Vajolet is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Vajolet is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Vajolet.  If not, see <http://www.gnu.org/licenses/>
*/

#include <iostream>
#include <iomanip>
#include <algorithm>
#include "board.h"
#include "bitops.h"
#include "data.h"
#include "movegen.h"
#include "transposition.h"
#include "eval.h"



U64 materialKBNvsk;
U64 materialKvskBN;
U64 materialKPvsk;
U64 materialKvskp;
U64 materialKPvskn;
U64 materialKPvskb;
U64 materialKNvskp;
U64 materialKBvskp;
/*
const int attackPatternFlag[Board::lastBitboard]={0,0,16,8,4,2,1,0,0,0,16,8,4,2,1,0};
//						 0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1
const int flagTable[32]={0,0,0,0,0,0,0,0,0,0,1,1,1,2,2,3,0,0,2,2,2,2,2,2,3,3,3,3,3,3,3,3};
*/

int blockedPawnsScaling[8]={64,64,64,64,64,32,16,1};

// king safety
bitMap kingRing[2];
int kingAttackersCount[2];
int kingAdjacentAttackersCount[2];
int kingAttackersWeight[2];
bitMap pseudoAttacks[Board::lastBitboard];


//bitMap attackBitmap[64];// one attack bitmap per square;
int kingSafety0=0,
	kingSafety1=0,
	kingSafety2=60;
int kingSafetyEval [100];
int bishopPairBonus=makeScore(156,156);	//12/11/2012
int bishopPairBonus2=makeScore(0,0); //13/11/2012 non sembra dare nessun beneficio =0

int bishopRedundancyPenaltyOpening=0; //13/11/2012 da approfondire
int bishopRedundancyPenaltyEndgame=150;
int rookRedundancy1Opening=60;
int rookRedundancy1Endgame=60;
int rookRedundancy2Opening=60;
int rookRedundancy2Endgame=60;
int knightRedundancyOpening=0;
int knightRedundancyEndgame=0;
int rookPawnCountOffset=36;
int rookPawnCountMalusOp=36;
int rookPawnCountMalusEnd=36;
int knightPawnCountOffset=36;
int knightPawnCountMalusOp=18;
int knightPawnCountMalusEnd=18;

int isolatedPawnPenaltyOpening[2][8]={{27,30,30,30,30,30,30,27},{30,33,33,33,33,33,33,30}}; //5/12/2012
int isolatedPawnPenaltyEndgame[2][8]={{63,66,66,69,69,66,66,63},{27,30,30,30,30,30,30,27}};
int doubledPawnPenaltyOpening[2]={15,15}; // 12/12/2012 messi a mano senza clop +52elo
int doubledPawnPenaltyEndgame[2]={6,0};
int chainedPawnBonusOpening[8]={30,33,33,36,36,33,33,30};	//6/12/2012
int chainedPawnBonusEndgame[8]={6,9,9,9,9,9,9,6};
int passedPawnBonusOpening=18;	//4/12/2012
int passedPawnBonusEndgame=33;
int passedPawnPenaltyFileAH=makeScore(0,60);	//11/12/2012 messo a mano senza clop
int passedPawnSupportedBonus=makeScore(0,30);//11/12/2012 messo a mano senza clop
int passedPawnNonBlockedBonus=makeScore(0,15);//11/12/2012 messo a mano senza clop
int backwardPawnPenaltyOpening[8]={24,24,18,12,6,6,6,6};	//10/12/2012
int backwardPawnPenaltyEndgame[8]={24,24,18,12,6,6,6,6};

int isolatedPawnPenalty[2][8];
int isolatedPawnHalfPenalty[2][8];
int doubledPawnPenalty[2];
int chainedPawnBonus[8];
int passedPawnBonus;
int backwardPawnPenalty[8];



int candidateBonusOpening=30;
int candidateBonusEndgame=3;

int spaceWeight=60;

int KingNearOwnPassedPawnBonus=42;	//2/1/2013
int KingNearEnemyPassedPawnBonus=66;


int knightOutpostBonus=15; // 9/1/2013
int bishopOutpostBonus=30;


/*int bishopThreathOpening=0;
int bishopThreathEndgame=450;
int knightThreathOpening=150;
int knightThreathEndgame=0;
int rookThreathOpening=0;
int rookThreathEndgame=0;
int queenThreathOpening=0;
int queenThreathEndgame=0;

int bishopUndefendedOpening=0;
int bishopUndefendedEndgame=0;
int knightUndefendedOpening=0;
int knightUndefendedEndgame=0;
int rookUndefendedOpening=0;
int rookUndefendedEndgame=0;
int queenUndefendedOpening=0;
int queenUndefendedEndgame=0;*/

//int undefendedMinorPenaltyOpening=0;
//int undefendedMinorPenaltyEndgame=0;

int undefendedMinorPenalty=makeScore(20,15);

//							     q,r,b,n
//int threatPenaltyOpening[8]={0,0,0,0,0,0,0,0};
//int threatPenaltyEndgame[8]={0,0,0,0,0,0,0,0};
int threatPenalty[8]={
		makeScore(0,0),
		makeScore(0,0),
		makeScore(15,20),//q
		makeScore(13,17),//r
		makeScore(12,15),//b
		makeScore(10,12),//n
		makeScore(5,5),//p
		makeScore(0,0)
		};



//int knightMobBonusOp[32]={0};
//int knightMobBonusEn[32]={0};
int knightMobBonus[32]={0};

//int bishopMobBonusOp[32]={0};
//int bishopMobBonusEn[32]={0};
int bishopMobBonus[32]={0};

//int rookMobBonusOp[32]={0};
//int rookMobBonusEn[32]={0};
int rookMobBonus[32]={0};


//int queenMobBonusOp[32]={0};
//int queenMobBonusEn[32]={0};
int queenMobBonus[32]={0};


//DA CLOPPARE!!
float knightMobOpA=0;
float knightMobOpM=6.33f;
float knightMobOpQ=-69;
float knightMobOp0=-585;

float knightMobEnA=0;
float knightMobEnM=5.01f;
float knightMobEnQ=-69;
float knightMobEn0=-1500;

float bishopMobOpA=0;
float bishopMobOpM=5.358f;//2
float bishopMobOpQ=-18;//-14
float bishopMobOp0=-267;//-20

float bishopMobEnA=0;
float bishopMobEnM=10.11f;//2
float bishopMobEnQ=-63;//-14
float bishopMobEn0=-387;//-20

float rookMobOpA=0;
float rookMobOpM=12.9f;//2
float rookMobOpQ=-81;//-20
float rookMobOp0=-219;//-20

float rookMobEnA=0;
float rookMobEnM=12;//3
float rookMobEnQ=39;//-20
float rookMobEn0=-450;//-20

float queenMobOpA=0;
float queenMobOpM=15;
float queenMobOpQ=-600;
float queenMobOp0=-1200;

float queenMobEnA=0;
float queenMobEnM=30;
float queenMobEnQ=-300;
float queenMobEn0=-1500;

//int rookOn7Opening=171;
//int rookOn7Endgame=108;
int rookOn7=makeScore(171,108);
int queenOn7Opening=24;
int queenOn7Endgame=78;
int queenOn7=makeScore(24,78);
//int rookOnPawnOpening=30;
//int rookOnPawnEndgame=90;
int rookOnPawn=makeScore(30,90);
int queenOnPawnOpening=21;
int queenOnPawnEndgame=150;
int queenOnPawn=makeScore(21,150);

//int rookOnOpenOpening=60;
//int rookOnOpenPawnEndgame=15;
int rookOnOpen=makeScore(60,15);
//int rookOnSemiOpening=30;
//int rookOnSemiPawnEndgame=15;
int rookOnSemi=makeScore(30,15);

int kingShieldBonus[4]={90,30,-60,-30}; // king defender near, king defender far, king attacker near, king attacker far


int badBishopOpening=24;
int badBishopEndgame=15;

int littleCenterControlOpening=15;
int bigCenterControlOpening=6;

int pawnEndgameBonusPst=51;


bitMap PawnAttackBitmap[2];
bitMap passedPawnBitmap[2];
bitMap zeroMobilityBitmap;

bitMap spaceMask[2]={
    (1ULL << C2) | (1ULL << D2) | (1ULL << E2) | (1ULL << F2) |
    (1ULL << C3) | (1ULL << D3) | (1ULL << E3) | (1ULL << F3) |
    (1ULL << C4) | (1ULL << D4) | (1ULL << E4) | (1ULL << F4),
    (1ULL << C7) | (1ULL << D7) | (1ULL << E7) | (1ULL << F7) |
    (1ULL << C6) | (1ULL << D6) | (1ULL << E6) | (1ULL << F6) |
    (1ULL << C5) | (1ULL << D5) | (1ULL << E5) | (1ULL << F5)
  };

bitMap outpostMask[2]={
	(1ULL << C3) | (1ULL << D3) | (1ULL << E3) | (1ULL << F3) |
	(1ULL << B4) | (1ULL << C4) | (1ULL << D4) | (1ULL << E4) | (1ULL << F4) | (1ULL << G4) |
	(1ULL << B5) | (1ULL << C5) | (1ULL << D5) | (1ULL << E5) | (1ULL << F5) | (1ULL << G5) |
	(1ULL << B6) | (1ULL << C6) | (1ULL << D6) | (1ULL << E6) | (1ULL << F6) | (1ULL << G6) |
	(1ULL << C7) | (1ULL << D7) | (1ULL << E7) | (1ULL << F7),

	(1ULL << C6) | (1ULL << D6) | (1ULL << E6) | (1ULL << F6) |
	(1ULL << B5) | (1ULL << C5) | (1ULL << D5) | (1ULL << E5) | (1ULL << F5) | (1ULL << G5) |
	(1ULL << B4) | (1ULL << C4) | (1ULL << D4) | (1ULL << E4) | (1ULL << F4) | (1ULL << G4) |
	(1ULL << B3) | (1ULL << C3) | (1ULL << D3) | (1ULL << E3) | (1ULL << F3) | (1ULL << G3) |
	(1ULL << C2) | (1ULL << D2) | (1ULL << E2) | (1ULL << F2)

};

bitMap littleCenter={(1ULL << D4) | (1ULL << D5) | (1ULL << E4) | (1ULL << E5)};
bitMap bigCenter={
	(1ULL << C3) | (1ULL << D3) | (1ULL << E3) | (1ULL << F3) |
	(1ULL << C6) | (1ULL << D6) | (1ULL << E6) | (1ULL << F6) |
	(1ULL << C4) | (1ULL << C5) | (1ULL << F4) | (1ULL << F5) 
	};




const int MateTable[64] = {
    100, 90, 80, 70, 70, 80, 90, 100,
     90, 70, 60, 50, 50, 60, 70,  90,
     80, 60, 40, 30, 30, 40, 60,  80,
     70, 50, 30, 20, 20, 30, 50,  70,
     70, 50, 30, 20, 20, 30, 50,  70,
     80, 60, 40, 30, 30, 40, 60,  80,
     90, 70, 60, 50, 50, 60, 70,  90,
    100, 90, 80, 70, 70, 80, 90, 100,
};

const int KBNKMateTable [2][64] = {{
    200, 190, 180, 170, 160, 150, 140, 130,
    190, 180, 170, 160, 150, 140, 130, 140,
    180, 170, 155, 140, 140, 125, 140, 150,
    170, 160, 140, 120, 110, 140, 150, 160,
    160, 150, 140, 110, 120, 140, 160, 170,
    150, 140, 125, 140, 140, 155, 170, 180,
    140, 130, 140, 150, 160, 170, 180, 190,
    130, 140, 150, 160, 170, 180, 190, 200
  },{
	130, 140, 150, 160, 170, 180, 190, 200,
	140, 130, 140, 150, 160, 170, 180, 190,
	150, 140, 125, 140, 140, 155, 170, 180,
	160, 150, 140, 110, 120, 140, 160, 170,
	170, 160, 140, 120, 110, 140, 150, 160,
	180, 170, 155, 140, 140, 125, 140, 150,
	190, 180, 170, 160, 150, 140, 130, 140,
    200, 190, 180, 170, 160, 150, 140, 130
  
}};

/*************************************************
 * EVAL TRACE
 *************************************************/

score traceVar[30][2];
score traceTemp[2];
void printTrace(){
	std::cout << std::setw(21) << "Eval term " << "|    White    |    Black    |     Total     \n"
	          <<             "                     |   MG    EG  |   MG    EG  |   MG     EG   \n"
	          <<             "---------------------+-------------+-------------+---------------\n";
	std::cout << std::setw(20) << "Material, PST, Tempo" << " |   ---   --- |   ---   --- | "
	          << std::setw(6)  << traceVar[0][0]/300.0 << " "
	          << std::setw(6)  << traceVar[0][1]/300.0 << " \n";
	std::cout << std::setw(20) << "Material Imbalance" << " |   ---   --- |   ---   --- | "
		      << std::setw(6)  << traceVar[1][0]/300.0 << " "
			  << std::setw(6)  << traceVar[1][1]/300.0 << " \n";
	std::cout << std::setw(20) << "Pawn" << " |   ---   --- |   ---   --- | "
			  << std::setw(6)  << traceVar[2][0]/300.0 << " "
			  << std::setw(6)  << traceVar[2][1]/300.0 << " \n";
	std::cout << std::setw(20) << "Passed Pawn"<< " | " << std::noshowpos
              << std::setw(5)  << traceVar[3][0]/300.0 << " "
              << std::setw(5)  << traceVar[3][1]/300.0 << " | "
              << std::setw(5)  << -traceVar[4][0]/300.0 << " "
              << std::setw(5)  << -traceVar[4][1]/300.0 << " | "
              << std::showpos
              << std::setw(6)  << (traceVar[3][0]+traceVar[4][0])/300.0 << " "
              << std::setw(6)  << (traceVar[3][1]+traceVar[4][1])/300.0 << " \n";
	std::cout << std::setw(20) << "Queen"<< " | " << std::noshowpos
	              << std::setw(5)  << traceVar[8][0]/300.0 << " "
	              << std::setw(5)  << traceVar[8][1]/300.0 << " | "
	              << std::setw(5)  << -traceVar[12][0]/300.0 << " "
	              << std::setw(5)  << -traceVar[12][1]/300.0 << " | "
	              << std::showpos
	              << std::setw(6)  << (traceVar[8][0]+traceVar[12][0])/300.0 << " "
	              << std::setw(6)  << (traceVar[8][1]+traceVar[12][1])/300.0 << " \n";
	std::cout << std::setw(20) << "Rook"<< " | " << std::noshowpos
	              << std::setw(5)  << traceVar[7][0]/300.0 << " "
	              << std::setw(5)  << traceVar[7][1]/300.0 << " | "
	              << std::setw(5)  << -traceVar[11][0]/300.0 << " "
	              << std::setw(5)  << -traceVar[11][1]/300.0 << " | "
	              << std::showpos
	              << std::setw(6)  << (traceVar[7][0]+traceVar[11][0])/300.0 << " "
	              << std::setw(6)  << (traceVar[7][1]+traceVar[11][1])/300.0 << " \n";
	std::cout << std::setw(20) << "Bishop"<< " | " << std::noshowpos
	              << std::setw(5)  << traceVar[6][0]/300.0 << " "
	              << std::setw(5)  << traceVar[6][1]/300.0 << " | "
	              << std::setw(5)  << -traceVar[10][0]/300.0 << " "
	              << std::setw(5)  << -traceVar[10][1]/300.0 << " | "
	              << std::showpos
	              << std::setw(6)  << (traceVar[6][0]+traceVar[10][0])/300.0 << " "
	              << std::setw(6)  << (traceVar[6][1]+traceVar[10][1])/300.0 << " \n";
	std::cout << std::setw(20) << "Knight"<< " | " << std::noshowpos
	              << std::setw(5)  << traceVar[5][0]/300.0 << " "
	              << std::setw(5)  << traceVar[5][1]/300.0 << " | "
	              << std::setw(5)  << -traceVar[9][0]/300.0 << " "
	              << std::setw(5)  << -traceVar[9][1]/300.0 << " | "
	              << std::showpos
	              << std::setw(6)  << (traceVar[5][0]+traceVar[9][0])/300.0 << " "
	              << std::setw(6)  << (traceVar[5][1]+traceVar[9][1])/300.0 << " \n";
	std::cout << std::setw(20) << "Center Control" << " |   ---   --- |   ---   --- | "
				  << std::setw(6)  << traceVar[13][0]/300.0 << " "
				  << std::setw(6)  << traceVar[13][1]/300.0 << " \n";
	std::cout << std::setw(20) << "Space" << " |   ---   --- |   ---   --- | "
				  << std::setw(6)  << traceVar[14][0]/300.0 << " "
				  << std::setw(6)  << traceVar[14][1]/300.0 << " \n";
	std::cout << std::setw(20) << "Threat"<< " | " << std::noshowpos
				  << std::setw(5)  << traceVar[15][0]/300.0 << " "
				  << std::setw(5)  << traceVar[15][1]/300.0 << " | "
				  << std::setw(5)  << -traceVar[16][0]/300.0 << " "
				  << std::setw(5)  << -traceVar[16][1]/300.0 << " | "
				  << std::showpos
				  << std::setw(6)  << (traceVar[15][0]+traceVar[16][0])/300.0 << " "
				  << std::setw(6)  << (traceVar[15][1]+traceVar[16][1])/300.0 << " \n";
	std::cout << std::setw(20) << "King Shield"<< " | " << std::noshowpos
				  << std::setw(5)  << traceVar[17][0]/300.0 << " "
				  << std::setw(5)  << traceVar[17][1]/300.0 << " | "
				  << std::setw(5)  << -traceVar[18][0]/300.0 << " "
				  << std::setw(5)  << -traceVar[18][1]/300.0 << " | "
				  << std::showpos
				  << std::setw(6)  << (traceVar[17][0]+traceVar[18][0])/300.0 << " "
				  << std::setw(6)  << (traceVar[17][1]+traceVar[18][1])/300.0 << " \n";
	std::cout << std::setw(20) << "King Safety"<< " | " << std::noshowpos
				  << std::setw(5)  << traceVar[19][0]/300.0 << " "
				  << std::setw(5)  << traceVar[19][1]/300.0 << " | "
				  << std::setw(5)  << -traceVar[20][0]/300.0 << " "
				  << std::setw(5)  << -traceVar[20][1]/300.0 << " | "
				  << std::showpos
				  << std::setw(6)  << (traceVar[19][0]+traceVar[20][0])/300.0 << " "
				  << std::setw(6)  << (traceVar[19][1]+traceVar[20][1])/300.0 << " \n";
	std::cout <<             "---------------------+-------------+-------------+---------------\n";

}
//------------------------------------------------
int Board::evalWpawn(unsigned int sq, bitMap * weakPawns){

	int result=0;
	bool passed, isolated, doubled, opposed, chain, backward;
	bitMap ourPawns =boards[whitePawns];
	bitMap theirPawns =boards[blackPawns];
	bitMap b;
	int file =FILES[sq];
	int rank =RANKS[sq];
	// Our rank plus previous one. Used for chain detection
    b = RANKMASK[sq] | RANKMASK[sq-8];
    // Flag the pawn as passed, isolated, doubled or member of a pawn
    // chain (but not the backward one).
    chain    = (ourPawns   & ISOLATED_PAWN[sq] & b)!=0;
	isolated = (ourPawns   & ISOLATED_PAWN[sq])==0;
    doubled  = (ourPawns   & SQUARES_IN_FRONT_OF[0][sq])!=0;
    opposed  = (theirPawns & SQUARES_IN_FRONT_OF[0][sq])!=0;
    passed   = (theirPawns & PASSED_PAWN[0][sq])==0;
	


	backward=false;
	if(!(passed | isolated | chain) &&  
			!(ourPawns & PASSED_PAWN[1][sq+8] & ISOLATED_PAWN[sq])){	// non ci sono nostri pedoni dietro a noi
		b = RANKMASK[sq+8]& ISOLATED_PAWN[sq];
		while (!(b & (ourPawns | theirPawns))){
              b <<= 8;
		}
		backward = ((b | (b << 8)) & theirPawns)!=0;
		
		

	}
	
	if (isolated){
		result-= isolatedPawnPenalty[opposed][file];
        //s[0] -= isolatedPawnPenaltyOpening[opposed][file];
		//s[1] -= isolatedPawnPenaltyEndgame[opposed][file];
		*weakPawns=BITSET[sq];

	}
	else{
		if(!(ourPawns & (KINGSHIELD[0][sq] | KINGSHIELD[1][sq]))){
			result-= isolatedPawnHalfPenalty[opposed][file];
			//s[0] -= isolatedPawnPenaltyOpening[opposed][file]/2;
			//s[1] -= isolatedPawnPenaltyEndgame[opposed][file]/2;
			*weakPawns=BITSET[sq];
		}
	}
	
    if (doubled){
    	result-= doubledPawnPenalty[opposed];
		//s[0] -= doubledPawnPenaltyOpening[opposed];
		//s[1] -= doubledPawnPenaltyEndgame[opposed];
		*weakPawns=BITSET[sq];
	}

    if (backward){
    	result-= backwardPawnPenalty[rank];
        //s[0] -= backwardPawnPenaltyOpening[rank];
		//s[1] -= backwardPawnPenaltyEndgame[rank];
		*weakPawns=BITSET[sq];
	}
	
    if (chain){
    	result+= chainedPawnBonus[file];
        //s[0] += chainedPawnBonusOpening[file];
		//s[1] += chainedPawnBonusEndgame[file];
	}


	//passed pawn
	if(passed &&!doubled){
		int r=rank-1;
		int rr= r*(r-1);
		result+=makeScore(passedPawnBonusOpening * rr,passedPawnBonusEndgame * (rr + r + 1));
		//s[0] += passedPawnBonusOpening * rr;
		//s[1] += passedPawnBonusEndgame * (rr + r + 1);
		passedPawnBitmap[0]|=BITSET[sq];

		if(file==0 || file==7){
			result -=passedPawnPenaltyFileAH;
			//s[1] -= passedPawnPenaltyFileAH;
		}
		if(chain){
			result+=passedPawnSupportedBonus;
			//s[1]+=passedPawnSupportedBonus;
		}
	}
	
	if ( !passed && !isolated && !doubled && !opposed && bitCnt( PASSED_PAWN[0][sq] & theirPawns ) < bitCnt(PASSED_PAWN[0][sq-8] & ourPawns )){
		result+=makeScore(candidateBonusOpening*(rank-1),candidateBonusEndgame*(rank-1));
		//s[0]+=candidateBonusOpening*(rank-1);
		//s[1]+=candidateBonusEndgame*(rank-1);

	}
	return result;
}

int Board::evalBpawn(unsigned int sq, bitMap * weakPawns){
	int result=0;
	bool passed, isolated, doubled, opposed, chain, backward;
	bitMap ourPawns =boards[blackPawns];
	bitMap theirPawns =boards[whitePawns];
	bitMap b;
	int file =FILES[sq];
	int rank =RANKS[sq];
	// Our rank plus previous one. Used for chain detection
    b = RANKMASK[sq] | RANKMASK[sq+8];
    // Flag the pawn as passed, isolated, doubled or member of a pawn
    // chain (but not the backward one).
    chain    = (ourPawns   & ISOLATED_PAWN[sq] & b)!=0;
	isolated = (ourPawns   & ISOLATED_PAWN[sq])==0;
    doubled  = (ourPawns   & SQUARES_IN_FRONT_OF[1][sq])!=0;
    opposed  = (theirPawns & SQUARES_IN_FRONT_OF[1][sq])!=0;
    passed   = (theirPawns & PASSED_PAWN[1][sq])==0;

	backward=false;
	if(!(passed | isolated | chain) &&  
				!(ourPawns & PASSED_PAWN[0][sq-8] & ISOLATED_PAWN[sq])){	// non ci sono nostri pedoni dietro a noi
		b = RANKMASK[sq-8]& ISOLATED_PAWN[sq];
		while (!(b & (ourPawns | theirPawns))){
              b >>= 8;
		}
		backward = ((b | (b >> 8)) & theirPawns)!=0;
		
		
	}

	
	if (isolated){
		result+= isolatedPawnPenalty[opposed][file];
        //s[0] += isolatedPawnPenaltyOpening[opposed][file];
		//s[1] += isolatedPawnPenaltyEndgame[opposed][file];
		*weakPawns=BITSET[sq];
	}
	else{
		if(!(ourPawns & (KINGSHIELD[0][sq] | KINGSHIELD[1][sq]))){
			result+= isolatedPawnHalfPenalty[opposed][file];
			//s[0] += isolatedPawnPenaltyOpening[opposed][file]/2;
			//s[1] += isolatedPawnPenaltyEndgame[opposed][file]/2;
			*weakPawns=BITSET[sq];
		}
	}
	
    if (doubled){
    	result+=doubledPawnPenalty[opposed];
		//s[0] += doubledPawnPenaltyOpening[opposed];
		//s[1] += doubledPawnPenaltyEndgame[opposed];
		*weakPawns=BITSET[sq];
	}
	
    if (backward){
    	result += backwardPawnPenalty[7-rank];
        //s[0] += backwardPawnPenaltyOpening[7-rank];
		//s[1] += backwardPawnPenaltyEndgame[7-rank];
		*weakPawns=BITSET[sq];
	}
    if (chain){
    	result-=chainedPawnBonus[file];
        //s[0] -= chainedPawnBonusOpening[file];
		//s[1] -= chainedPawnBonusEndgame[file];
	}



	//passed pawn
	if(passed &&!doubled){
		int r=6-rank;
		int rr= r*(r-1);
		result -=makeScore(passedPawnBonusOpening * rr,passedPawnBonusEndgame * (rr + r + 1));
		//s[0] -= passedPawnBonusOpening * rr;
		//s[1] -= passedPawnBonusEndgame * (rr + r + 1);
		passedPawnBitmap[1]|=BITSET[sq];
		if(file==0 || file==7){
			result+=passedPawnPenaltyFileAH;
			//s[1] += passedPawnPenaltyFileAH;
		}
		if(chain){
			result-=passedPawnSupportedBonus;
			//s[1]-=passedPawnSupportedBonus;
		}
		
	}
	if ( !passed && !isolated && !doubled && !opposed && bitCnt( PASSED_PAWN[1][sq] & theirPawns ) < bitCnt(PASSED_PAWN[1][sq+8] & ourPawns ) ){
		result -=makeScore(candidateBonusOpening*(6-rank),candidateBonusEndgame*(6-rank));
		//s[0]-=candidateBonusOpening*(6-rank);
		//s[1]-=candidateBonusEndgame*(6-rank);
	}
	return result;
}
template <bool trace>
score Board::eval(){
	//Search::evalCall++;

	
	
	zeroMobilityBitmap=0;
	int minorpiecesCount=0;
	score eval;
	for(int i=0;i<Board::lastBitboard;i++){
		pseudoAttacks[i]=0;
	}
	

	int res=makeScore(Material,Material);

	//result[0]=Material;
	//result[1]=Material;

	unsigned int kingSquare[2];
	kingSquare[0]=firstOne(boards[whiteKing]);
	kingRing[0]=KINGSHIELD[0][kingSquare[0]];
	pseudoAttacks[Board::whiteKing]=KING_ATTACKS[kingSquare[0]];
	kingSquare[1]=firstOne(boards[blackKing]);
	kingRing[1]=KINGSHIELD[1][kingSquare[1]];
	pseudoAttacks[Board::blackKing]=KING_ATTACKS[kingSquare[1]];
	
	
	
	if( (materialKey==materialKPvskn) ||
		(materialKey==materialKPvskb) ||
		(materialKey==materialKNvskp) ||
		(materialKey==materialKBvskp)) {
			res=0;
			//result[0]=0;
			//result[1]=0;
	}
	

	//std::cout<<"material="<<Material<<std::endl;

	/*-----------------------------------------
	PST
	-------------------------------------------*/
	for(int sq=0;sq<64;sq++){
		//std::cout<<Board::PIECECHARS[ square[sq]]<<":"<<PST[Board::opening][square[sq]][sq]<<":"<<PST[Board::endgame][square[sq]][sq]<<std::endl;
		//result[Board::opening]+=PST[Board::opening][square[sq]][sq];
		//result[Board::endgame]+=PST[Board::endgame][square[sq]][sq];
		res+=PST[square[sq]][sq];
	}

	
	
	// tempo bonus
	//seems not working 24/10/2012
	/*if(nextMove){
		result[0] -=10;
		result[1] -=5;
	}
	else{
		result[0] +=10;
		result[1] +=5;
	}*/

	if(trace){
		traceVar[0][0]=mg_value(res);
		traceVar[0][1]=eg_value(res);

	}

	/********************************************
	* SPECIALIZED ENDGAME & SCALING FUNCTION
	*********************************************/
	if(!boards[blackPawns] && !boards[whitePawns]){
		if(totalBlackPieces==0 && totalWhitePieces==0){
			return 0;
		}
		if(totalBlackPieces<=2*PIECESCORE[whiteKnights] && !pieceCount[blackRooks] && totalWhitePieces==0){
			return 0;
		}
		if(totalWhitePieces<=2*PIECESCORE[whiteKnights] && !pieceCount[whiteRooks] && totalBlackPieces==0){
			return 0;
		}

	}
	if(materialKey==materialKPvsk){
		unsigned int bKing,wPawn;

		//wKing=firstOne(boards[whiteKing]);
		bKing=firstOne(boards[blackKing]);
		wPawn=firstOne(boards[whitePawns]);
		if(RANKS[wPawn]>RANKS[bKing]){
			score temp =VALUE_KNOWN_WIN + 100 + RANKS[wPawn]*10;
			if(nextMove){
				temp= -temp;
			}
			return temp;
		}
		
	}
	else if (materialKey==materialKvskp){
		unsigned int wKing,bPawn;

		wKing=firstOne(boards[whiteKing]);
		//bKing=firstOne(boards[blackKing]);
		bPawn=firstOne(boards[whitePawns]);
		if(RANKS[bPawn]<RANKS[wKing]){
			score temp =-VALUE_KNOWN_WIN - 100 - (7-RANKS[bPawn])*10;
			if(nextMove){
				temp= -temp;
			}
			return temp;
		}

	}
	else if(materialKey==materialKBNvsk){
		unsigned int wKing,bKing;
		score temp;
		wKing=firstOne(boards[whiteKing]);
		bKing=firstOne(boards[blackKing]);
		if(boards[whiteBishops]& SQUARE_COLOR_BITMAP[1]){
			temp= VALUE_KNOWN_WIN+ 80 -(squareDistance[wKing][bKing]-3)*20 + KBNKMateTable[1][bKing];
		}else{
			temp= VALUE_KNOWN_WIN+ 80 -(squareDistance[wKing][bKing]-3)*20 + KBNKMateTable[0][bKing];
		}
		if(nextMove){
			temp= -temp;
		}
		return temp;
	}
	else if(materialKey==materialKvskBN){
		unsigned int wKing,bKing;
		wKing=firstOne(boards[whiteKing]);
		bKing=firstOne(boards[blackKing]);
		score temp;
		if(boards[blackBishops]& SQUARE_COLOR_BITMAP[1]){
			temp= -VALUE_KNOWN_WIN- 80 +(squareDistance[wKing][bKing]-3)*20 - KBNKMateTable[1][wKing];
		}else{
			temp= -VALUE_KNOWN_WIN- 80 +(squareDistance[wKing][bKing]-3)*20 - KBNKMateTable[0][wKing];
		}
		if(nextMove){
			temp= -temp;
		}
		return temp;
	}
	
	if(totalBlackPieces==0 && !boards[blackPawns] && totalWhitePieces!=0){
		// white can win
		unsigned int wKing,bKing;
		wKing=firstOne(boards[whiteKing]);
		bKing=firstOne(boards[blackKing]);
		score temp= Material+80-(squareDistance[wKing][bKing]-3)*20 +MateTable[bKing];
		if(pieceCount[whiteQueens] || pieceCount[whiteRooks] || (bitCnt(boards[whiteBishops]& SQUARE_COLOR_BITMAP[0]) && bitCnt(boards[whiteBishops]& SQUARE_COLOR_BITMAP[1]))) {
			temp+=VALUE_KNOWN_WIN;
		}
		if(nextMove){
			temp= -temp;
		}
		return temp;
		
	}else if(totalBlackPieces!=0 && totalWhitePieces==0 && !boards[whitePawns]){
		// black can win
		unsigned int wKing,bKing;
		wKing=firstOne(boards[whiteKing]);
		bKing=firstOne(boards[blackKing]);
		score temp= Material-80+(squareDistance[wKing][bKing]-3)*20 -MateTable[wKing];
		if(pieceCount[blackQueens] || pieceCount[blackRooks] || (bitCnt(boards[blackBishops]& SQUARE_COLOR_BITMAP[0]) && bitCnt(boards[blackBishops]& SQUARE_COLOR_BITMAP[1]))) {
			temp-=VALUE_KNOWN_WIN;
		}
		if(nextMove){
			temp= -temp;
		}
		return temp;
	}
	
	
	/********************************************
	* MATERIAL imbalance
	*********************************************/

	int MaterialResult=0;
	if(probeMaterialCache(materialKey,&MaterialResult)){
		
	}else
	{
		/********************************************
		*1) bishop pair
		********************************************/

		unsigned char lightSquaredBishop =bitCnt(boards[whiteBishops]& SQUARE_COLOR_BITMAP[0] );
		unsigned char darkSquaredBishop =bitCnt(boards[whiteBishops]& SQUARE_COLOR_BITMAP[1] );
		unsigned char whitePawnCount=pieceCount[whitePawns];
		unsigned char opponentMinorPieceCount= pieceCount[blackKnights]+pieceCount[blackBishops];
		if(lightSquaredBishop && darkSquaredBishop ){
			//white bishop pair
			MaterialResult+=bishopPairBonus;
			//MaterialResult[0] +=bishopPairBonusOpening;
			//MaterialResult[1] +=bishopPairBonusEndgame;
			if(opponentMinorPieceCount==0){
				MaterialResult+=bishopPairBonus2;
				//MaterialResult[0] +=bishopPairBonus2Opening;
				//MaterialResult[1] +=bishopPairBonus2Endgame;
			}

		
		}
		if(lightSquaredBishop>1){
			MaterialResult-=makeScore(bishopRedundancyPenaltyOpening*(lightSquaredBishop-1),bishopRedundancyPenaltyEndgame*(lightSquaredBishop-1));
			//MaterialResult[0] -=bishopRedundancyPenaltyOpening*(lightSquaredBishop-1);
			//MaterialResult[1] -=bishopRedundancyPenaltyEndgame*(lightSquaredBishop-1);
		}
		if(darkSquaredBishop>1){
			MaterialResult-=makeScore(bishopRedundancyPenaltyOpening*(darkSquaredBishop-1),bishopRedundancyPenaltyEndgame*(darkSquaredBishop-1));
			//MaterialResult[0] -=bishopRedundancyPenaltyOpening*(darkSquaredBishop-1);
			//MaterialResult[1] -=bishopRedundancyPenaltyEndgame*(darkSquaredBishop-1);
		}


		lightSquaredBishop =bitCnt(boards[blackBishops]& SQUARE_COLOR_BITMAP[0] );
		darkSquaredBishop =bitCnt(boards[blackBishops]& SQUARE_COLOR_BITMAP[1] );
		unsigned char blackPawnCount=pieceCount[blackPawns];
		opponentMinorPieceCount=pieceCount[whiteKnights]+pieceCount[whiteBishops];
		if(lightSquaredBishop && darkSquaredBishop ){
			//black bishop pair
			MaterialResult -= bishopPairBonus;
			//MaterialResult[0] -=bishopPairBonusOpening;
			//MaterialResult[1] -=bishopPairBonusEndgame;
			if(opponentMinorPieceCount==0){
				MaterialResult -= bishopPairBonus2;
				//MaterialResult[0] -=bishopPairBonus2Opening;
				//MaterialResult[1] -=bishopPairBonus2Endgame;
			}
		}
		if(lightSquaredBishop>1){
			MaterialResult+=makeScore(bishopRedundancyPenaltyOpening*(lightSquaredBishop-1),bishopRedundancyPenaltyEndgame*(lightSquaredBishop-1));
			//MaterialResult[0] +=bishopRedundancyPenaltyOpening*(lightSquaredBishop-1);
			//MaterialResult[1] +=bishopRedundancyPenaltyEndgame*(lightSquaredBishop-1);
		}
		if(darkSquaredBishop>1){
			MaterialResult+=makeScore(bishopRedundancyPenaltyOpening*(darkSquaredBishop-1),bishopRedundancyPenaltyEndgame*(darkSquaredBishop-1));
			//MaterialResult[0] +=bishopRedundancyPenaltyOpening*(darkSquaredBishop-1);
			//MaterialResult[1] +=bishopRedundancyPenaltyEndgame*(darkSquaredBishop-1);
		}

		/******************************************
		* redundant rooks penalty
		*******************************************/
		unsigned char rookCnt=pieceCount[whiteRooks];
		unsigned char queenCnt=pieceCount[whiteQueens];
		if (rookCnt > 0){
			MaterialResult -=makeScore(rookRedundancy1Opening*(rookCnt-1)+rookRedundancy2Opening*queenCnt,rookRedundancy1Endgame*(rookCnt-1)+rookRedundancy2Endgame*queenCnt);
			//MaterialResult[0]-=rookRedundancy1Opening*(rookCnt-1)+rookRedundancy2Opening*queenCnt;
			//MaterialResult[1]-=rookRedundancy1Endgame*(rookCnt-1)+rookRedundancy2Endgame*queenCnt;
			if(whitePawnCount>rookPawnCountOffset){
				MaterialResult -=makeScore(rookCnt*(whitePawnCount-rookPawnCountOffset)*rookPawnCountMalusOp,rookCnt*(whitePawnCount-rookPawnCountOffset)*rookPawnCountMalusEnd);
				//MaterialResult[0]-=rookCnt*(whitePawnCount-rookPawnCountOffset)*rookPawnCountMalusOp;
				//MaterialResult[1]-=rookCnt*(whitePawnCount-rookPawnCountOffset)*rookPawnCountMalusEnd;
			}
		}

		rookCnt=pieceCount[blackRooks];
		queenCnt=pieceCount[blackQueens];
		if (rookCnt > 0){
			MaterialResult +=makeScore(rookRedundancy1Opening*(rookCnt-1)+rookRedundancy2Opening*queenCnt,rookRedundancy1Endgame*(rookCnt-1)+rookRedundancy2Endgame*queenCnt);
			//MaterialResult[0]+=rookRedundancy1Opening*(rookCnt-1)+rookRedundancy2Opening*queenCnt;
			//MaterialResult[1]+=rookRedundancy1Endgame*(rookCnt-1)+rookRedundancy2Endgame*queenCnt;
			if(blackPawnCount>rookPawnCountOffset){
				MaterialResult +=makeScore(rookCnt*(blackPawnCount-rookPawnCountOffset)*rookPawnCountMalusOp,rookCnt*(blackPawnCount-rookPawnCountOffset)*rookPawnCountMalusEnd);
				//MaterialResult[0]+=rookCnt*(blackPawnCount-rookPawnCountOffset)*rookPawnCountMalusOp;
				//MaterialResult[1]+=rookCnt*(blackPawnCount-rookPawnCountOffset)*rookPawnCountMalusEnd;
			}
		}
		/*************************************************************
		* Knight redundancy
		**************************************************************/
		unsigned char knightCnt=pieceCount[whiteKnights];
		if(knightCnt>1){
			MaterialResult -= makeScore(knightRedundancyOpening*(knightCnt-1),knightRedundancyEndgame*(knightCnt-1));
			//MaterialResult[0]-=knightRedundancyOpening*(knightCnt-1);
			//MaterialResult[1]-=knightRedundancyEndgame*(knightCnt-1);
			if(whitePawnCount>knightPawnCountOffset){
				MaterialResult += makeScore(knightCnt*(whitePawnCount-knightPawnCountOffset)*knightPawnCountMalusOp,knightCnt*(whitePawnCount-knightPawnCountOffset)*knightPawnCountMalusEnd);
				//MaterialResult[0]+=knightCnt*(whitePawnCount-knightPawnCountOffset)*knightPawnCountMalusOp;
				//MaterialResult[1]+=knightCnt*(whitePawnCount-knightPawnCountOffset)*knightPawnCountMalusEnd;
			}
		}

		knightCnt=pieceCount[blackKnights];
		if(knightCnt>1){
			MaterialResult += makeScore(knightRedundancyOpening*(knightCnt-1),knightRedundancyEndgame*(knightCnt-1));
			//MaterialResult[0]+=knightRedundancyOpening*(knightCnt-1);
			//MaterialResult[1]+=knightRedundancyEndgame*(knightCnt-1);
			if(blackPawnCount>knightPawnCountOffset){
				MaterialResult -= makeScore(knightCnt*(blackPawnCount-knightPawnCountOffset)*knightPawnCountMalusOp,knightCnt*(blackPawnCount-knightPawnCountOffset)*knightPawnCountMalusEnd);
				//MaterialResult[0]-=knightCnt*(blackPawnCount-knightPawnCountOffset)*knightPawnCountMalusOp;
				//MaterialResult[1]-=knightCnt*(blackPawnCount-knightPawnCountOffset)*knightPawnCountMalusEnd;
			}
		}

		insertMaterialCache(materialKey,MaterialResult);

	}
	
	res +=MaterialResult;
	//result[0]+=MaterialResult[0];
	//result[1]+=MaterialResult[1];

	if(trace){
		traceVar[1][0]=mg_value(MaterialResult);
		traceVar[1][1]=eg_value(MaterialResult);
	}

	/********************************************************
	* PAWN STRUCTURE EVALUTATION
	*
	********************************************************/

	int pawnResult=0;
	bitMap weakPawns;
	if(probePawnCache(pawnKey,&pawnResult,PawnAttackBitmap,passedPawnBitmap,&weakPawns)){
		
	}else{
		// calcola pawn attack bitmaps
		bitMap tempPiece = boards[Board::whitePawns];
		PawnAttackBitmap[0]= ((tempPiece& ~(FILEMASK[H1]))<<9);
		PawnAttackBitmap[0]|= ((tempPiece& ~(FILEMASK[A1]))<<7);
		

		tempPiece = boards[Board::blackPawns];
		PawnAttackBitmap[1]= ((tempPiece& ~(FILEMASK[H1]))>>7);
		PawnAttackBitmap[1]|= ((tempPiece& ~(FILEMASK[A1]))>>9);

		
		passedPawnBitmap[0]=0;
		passedPawnBitmap[1]=0;

		weakPawns=0;


		bitMap t=boards[Board::whitePawns];
		while(t){
			unsigned int p = firstOne(t);
			pawnResult+=evalWpawn(p, &weakPawns);
			t&=t-1;
		}
		t=boards[Board::blackPawns];
		while(t){
			unsigned int p = firstOne(t);
			pawnResult+=evalBpawn(p,&weakPawns);
			t&=t-1;
		}

		insertPawnCache(pawnKey, pawnResult, PawnAttackBitmap,passedPawnBitmap,0);
		
		
	}

	res+=pawnResult;
	//result[0]=mg_value(res);
	//result[1]=eg_value(res);
	//result[0]+=pawnResult[0];
	//result[1]+=pawnResult[1];
	
	if(trace){
		traceVar[2][0]=mg_value(pawnResult);
		traceVar[2][1]=eg_value(pawnResult);
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	
	
	
	/********************************************************************
	* passed pawn post evalutation
	*	non blocked pawn
	*	re vicino alla casa di blocco
	**********************************************************************/

	bitMap t=passedPawnBitmap[0];
	while(t){
		unsigned int p = firstOne(t);
		if(square[p+8]==Board::empty){ // non bloccato;
			res+=passedPawnNonBlockedBonus;
		}
		res+=makeScore(0,(8-squareDistance[p+8][firstOne(boards[whiteKing])])*KingNearOwnPassedPawnBonus-(8-squareDistance[p+8][firstOne(boards[blackKing])])*KingNearEnemyPassedPawnBonus);
		//result[1]+=(8-squareDistance[p+8][firstOne(boards[whiteKing])])*KingNearOwnPassedPawnBonus;
		//result[1]-=(8-squareDistance[p+8][firstOne(boards[blackKing])])*KingNearEnemyPassedPawnBonus;
		t&=t-1;
	}
	if(trace){
		traceVar[3][0]=mg_value(res)-traceTemp[0];
		traceVar[3][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}
	t=passedPawnBitmap[1];
	while(t){
		unsigned int p = firstOne(t);
		if(square[p-8]==Board::empty){
			res-=passedPawnNonBlockedBonus;
		}
		res -= makeScore(0,(8-squareDistance[p-8][firstOne(boards[blackKing])])*KingNearOwnPassedPawnBonus-(8-squareDistance[p-8][firstOne(boards[whiteKing])])*KingNearEnemyPassedPawnBonus);
		//result[1]-=(8-squareDistance[p-8][firstOne(boards[blackKing])])*KingNearOwnPassedPawnBonus;
		//result[1]+=(8-squareDistance[p-8][firstOne(boards[whiteKing])])*KingNearEnemyPassedPawnBonus;
		t&=t-1;
	}
	if(trace){
		traceVar[4][0]=mg_value(res)-traceTemp[0];
		traceVar[4][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}







	kingAttackersCount[0]=bitCnt(kingRing[0] &PawnAttackBitmap[1]);
	kingAttackersCount[1]=bitCnt(kingRing[1] &PawnAttackBitmap[0]);
	kingAttackersWeight[0]=0;
	kingAttackersWeight[1]=0;
	kingAdjacentAttackersCount[0]=0;
	kingAdjacentAttackersCount[1]=0;
	pseudoAttacks[Board::whitePawns]=PawnAttackBitmap[0];
	pseudoAttacks[Board::blackPawns]=PawnAttackBitmap[1];


	bitMap targetBitmap=0xFFFFFFFFFFFFFFFFull;
	bitMap occupiedSquares=boards[Board::occupiedSquares];

	bitMap supportedSquares[2]={PawnAttackBitmap[0]| pseudoAttacks[Board::whiteKing] ,PawnAttackBitmap[1]|pseudoAttacks[Board::blackKing]};
	
	
	// valutazione cavallo
	t=boards[whiteKnights];
	while(t){
		//minorpiecesCount++;
		score bonus=0;
		unsigned int p = firstOne(t);
		bitMap b=BITSET[p];
		bitMap attack=KNIGHT_ATTACKS[p];
		supportedSquares[0]|=attack;
		
		bitMap pseudoAtt=KNIGHT_ATTACKS[p];
		pseudoAttacks[Board::whiteKnights]|=pseudoAtt;
		if(pseudoAtt & kingRing[1]){
			kingAttackersCount[1]++;
			kingAttackersWeight[1]+=2;
			bitMap bb=pseudoAtt & pseudoAttacks[Board::blackKing];
			if(bb){
				kingAdjacentAttackersCount[1]+=bitCnt(bb);
			}
		}
		int mob;
		if(pinnedPieces& b){
			mob=0;
		}else{
			mob=bitCnt(attack & ~boards[Board::whitePieces] &~PawnAttackBitmap[1]);
		}
		res += knightMobBonus[mob];
		if(mob==0){zeroMobilityBitmap|=BITSET[p];}
		//result[0] += knightMobBonusOp[mob];
		//result[1] += knightMobBonusEn[mob];


		if((b & outpostMask[0]) && 
			!(PASSED_PAWN[0][p] & ~FILEMASK[p] & boards[blackPawns])
		){
			bonus=knightOutpostBonus;
			if(PawnAttackBitmap[0] & b){
				bonus+=knightOutpostBonus/2;
				if(!boards[blackKnights] &&
					!(SQUARE_COLOR_BITMAP[SQUARE_COLOR[p]] &	boards[blackBishops])){
						bonus+=knightOutpostBonus/2;
					
				}
			}
			
		}
		res+=makeScore(bonus,bonus);
		//result[0]+=bonus;
		//result[1]+=bonus;

		/*if(!(PawnAttackBitmap[0] & b)){ // unsupported knight
			result[0]-=knightUndefendedOpening;
			result[1]-=knightUndefendedEndgame;
		}
		if((PawnAttackBitmap[1] & b)){ // threath
			result[0]-=knightThreathOpening;
			result[1]-=knightThreathEndgame;
		}*/

		
		
		
		t&=t-1;
	}
	if(trace){
		traceVar[5][0]=mg_value(res)-traceTemp[0];
		traceVar[5][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}


	// valutazione alfiere
	t=boards[whiteBishops];
	while(t){
		//minorpiecesCount++;
		score bonus=0;
		unsigned int p = firstOne(t);
		bitMap b=BITSET[p];
		bitMap attack=BISHOPMOVES(p);
		supportedSquares[0]|=attack;
		occupiedSquares=boards[Board::blackPieces]|boards[Board::whitePawns];
		bitMap pseudoAtt=BISHOPATTACKS(p);
		pseudoAttacks[Board::whiteBishops]|=pseudoAtt;
		occupiedSquares=boards[Board::occupiedSquares];
		if(pseudoAtt & kingRing[1]){
			kingAttackersCount[1]++;
			kingAttackersWeight[1]+=2;
			bitMap bb=pseudoAtt & pseudoAttacks[Board::blackKing];
			if(bb){
				kingAdjacentAttackersCount[1]+=bitCnt(bb);
			}
		}
		int mob;
		if(pinnedPieces & b){
			mob=bitCnt(*SQUARES_BETWEEN_DIRECTION[kingSquare[0]][p] & attack & ~boards[Board::whitePieces] &~PawnAttackBitmap[1]);
		}else{
			mob=bitCnt(attack & ~boards[Board::whitePieces] &~PawnAttackBitmap[1]);
		}


		res+=bishopMobBonus[mob];
		if(mob==0){zeroMobilityBitmap|=BITSET[p];}
		//result[0] += bishopMobBonusOp[mob];
		//result[1] += bishopMobBonusEn[mob];

		
		if((b & outpostMask[0]) && 
			!(PASSED_PAWN[0][p] & ~FILEMASK[p] & boards[blackPawns])
		){
			bonus=bishopOutpostBonus;

			if(PawnAttackBitmap[0] & b){
				bonus+=bishopOutpostBonus/2;
				if(!boards[blackKnights] &&
					!(SQUARE_COLOR_BITMAP[SQUARE_COLOR[p]] &	boards[blackBishops])){
					bonus+=bishopOutpostBonus/2;
				}
			}
			
		}
		res+=makeScore(bonus,bonus);
		//result[0]+=bonus;
		//result[1]+=bonus;


		/*if(!(PawnAttackBitmap[0] & b)){ // unsupported bishop
			result[0]-=bishopUndefendedOpening;
			result[1]-=bishopUndefendedEndgame;
		}
		if((PawnAttackBitmap[1] & b)){ // threath
			result[0]-=bishopThreathOpening;
			result[1]-=bishopThreathEndgame;
		}*/
		if(b & SQUARE_COLOR_BITMAP[0]){
			// alfiere su casa chiara
			int n=bitCnt(SQUARE_COLOR_BITMAP[0] & boards[whitePawns])-bitCnt(SQUARE_COLOR_BITMAP[0] & boards[blackPawns]);
			if(n>=2){
				res-=makeScore(badBishopOpening*n,badBishopEndgame*n);
				//result[0]-=badBishopOpening*n;
				//result[1]-=badBishopEndgame*n;
			}
		}
		if(b & SQUARE_COLOR_BITMAP[1]){
			// alfiere su casa scura
			int n=bitCnt(SQUARE_COLOR_BITMAP[1] & boards[whitePawns])-bitCnt(SQUARE_COLOR_BITMAP[1] & boards[blackPawns]);
			if(n>=2){
				res-=makeScore(badBishopOpening*n,badBishopEndgame*n);
				//result[0]-=badBishopOpening*n;
				//result[1]-=badBishopEndgame*n;
			}
		}

		t&=t-1;
	}
	if(trace){
		traceVar[6][0]=mg_value(res)-traceTemp[0];
		traceVar[6][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}


	// valutazione torre
	t=boards[whiteRooks];
	while(t){
		
		unsigned int p = firstOne(t);
		bitMap b=BITSET[p];
		int rank=RANKS[p];
		
		bitMap attack=ROOKMOVES(p);
		supportedSquares[0]|=attack;
		occupiedSquares=boards[Board::blackPieces]|boards[Board::whitePawns];
		bitMap pseudoAtt=ROOKATTACKS(p);
		pseudoAttacks[Board::whiteRooks]|=pseudoAtt;
		if(pseudoAtt & kingRing[1]){
			kingAttackersCount[1]++;
			kingAttackersWeight[1]+=3;
			bitMap bb=pseudoAtt & pseudoAttacks[Board::blackKing];
			if(bb){
				kingAdjacentAttackersCount[1]+=bitCnt(bb);
			}
		}
		occupiedSquares=boards[Board::occupiedSquares];
		int mob;
		if(pinnedPieces & b){
			mob=bitCnt(*SQUARES_BETWEEN_DIRECTION[kingSquare[0]][p] & attack & ~boards[Board::whitePieces] &~PawnAttackBitmap[1]);
		}else{
			mob=bitCnt(attack & ~boards[Board::whitePieces] &~PawnAttackBitmap[1]);
		}
		res+=rookMobBonus[mob];
		if(mob==0){zeroMobilityBitmap|=BITSET[p];}
		//result[0] += rookMobBonusOp[mob];
		//result[1] += rookMobBonusEn[mob];
		
		/*if(!(PawnAttackBitmap[0] & b)){ // unsupported rook
			result[0]-=rookUndefendedOpening;
			result[1]-=rookUndefendedEndgame;
		}
		if((PawnAttackBitmap[1] & b)){ // threath
			result[0]-=rookThreathOpening;
			result[1]-=rookThreathEndgame;
		}*/

		if(rank==6 && (boards[blackKing]&RANKMASK[H8])){ // torre in 7a con re avversario in 8a
			res+=rookOn7;
			//result[0]+=rookOn7Opening;
			//result[1]+=rookOn7Endgame;
		}
		if(rank>4 && (RANKMASK[p]&boards[blackPawns])){ // torre oltre dalla 5a traversa in su che ha pedoni sulla sua traversa
			res+=rookOnPawn;
			//result[0]+=rookOnPawnOpening;
			//result[1]+=rookOnPawnEndgame;
		}
		// torre su colonna aperta/semiaperta
		if(!(FILEMASK[p]& boards[whitePawns])){
			if(!(FILEMASK[p]& boards[blackPawns])){	// colonna aperta
				res+=rookOnOpen;
				//result[0]+=rookOnOpenOpening;
				//result[1]+=rookOnOpenPawnEndgame;
			}else{
				// colonna semiaperta
				res+=rookOnSemi;
				//result[0]+=rookOnSemiOpening;
				//result[1]+=rookOnSemiPawnEndgame;
			}
		}

		t&=t-1;
	}
	if(trace){
		traceVar[7][0]=mg_value(res)-traceTemp[0];
		traceVar[7][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}


	// valutazione donna
	t=boards[whiteQueens];
	while(t){
		
		unsigned int p = firstOne(t);
		bitMap b=BITSET[p];
		int rank= RANKS[p];
		bitMap attack=QUEENMOVES(p);
		supportedSquares[0]|=attack;
		occupiedSquares=boards[Board::blackPieces]|boards[Board::whitePawns];
		bitMap pseudoAtt=(BISHOPATTACKS(p)|ROOKATTACKS(p));
		pseudoAttacks[Board::whiteQueens]|=pseudoAtt;
		if(pseudoAtt & kingRing[1]){
			kingAttackersCount[1]++;
			kingAttackersWeight[1]+=5;
			bitMap bb=pseudoAtt & pseudoAttacks[Board::blackKing];
			if(bb){
				kingAdjacentAttackersCount[1]+=bitCnt(bb);
			}
		}
		
		occupiedSquares=boards[Board::occupiedSquares];
		int mob;
		if(pinnedPieces & b){
			mob=bitCnt(*SQUARES_BETWEEN_DIRECTION[kingSquare[0]][p]& attack & ~boards[Board::whitePieces] &~PawnAttackBitmap[1]);
		}else{
			mob=bitCnt(attack & ~boards[Board::whitePieces] &~PawnAttackBitmap[1]);
		}
		res+=queenMobBonus[mob];
		if(mob==0){zeroMobilityBitmap|=BITSET[p];}
		//result[0] += queenMobBonusOp[mob];
		//result[1] += queenMobBonusEn[mob];
		
		/*if(!(PawnAttackBitmap[0] & b)){ // unsupported rook
			result[0]-=queenUndefendedOpening;
			result[1]-=queenUndefendedEndgame;
		}
		if((PawnAttackBitmap[1] & b)){ // threath
			result[0]-=queenThreathOpening;
			result[1]-=queenThreathEndgame;
		}*/
		
		if(rank==6 && (boards[blackKing]&RANKMASK[H8])){ // donna in 7a con re avversario in 8a
			res+=queenOn7;
			//result[0]+=queenOn7Opening;
			//result[1]+=queenOn7Endgame;
		}
		if(rank>4 && (RANKMASK[p]&boards[blackPawns])){
			res+=queenOnPawn;
			//result[0]+=queenOnPawnOpening;
			//result[1]+=queenOnPawnEndgame;
		}


		t&=t-1;
	}
	if(trace){
		traceVar[8][0]=mg_value(res)-traceTemp[0];
		traceVar[8][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	//targetBitmap=~boards[Board::blackPieces];
	
	// valutazione cavallo
	t=boards[blackKnights];
	while(t){
		//minorpiecesCount++;
		score bonus=0;
		unsigned int p = firstOne(t);
		bitMap b=BITSET[p];

		bitMap attack=KNIGHT_ATTACKS[p];
		supportedSquares[1]|=attack;
		bitMap pseudoAtt=KNIGHT_ATTACKS[p];
		pseudoAttacks[Board::blackKnights]|=pseudoAtt;
		if(pseudoAtt & kingRing[0]){
			kingAttackersCount[0]++;
			kingAttackersWeight[0]+=2;
			bitMap bb=pseudoAtt & pseudoAttacks[Board::whiteKing];
			if(bb){
				kingAdjacentAttackersCount[0]+=bitCnt(bb);
			}
		}

		int mob;
		if(pinnedPieces& b){
			mob=0;
		}else{
			mob=bitCnt(attack & ~boards[Board::blackPieces] &~PawnAttackBitmap[0]);
		}
		res-=knightMobBonus[mob];
		if(mob==0){zeroMobilityBitmap|=BITSET[p];}
		//result[0] -= knightMobBonusOp[mob];
		//result[1] -= knightMobBonusEn[mob];

		if((b & outpostMask[1]) && 
			!(PASSED_PAWN[1][p] & ~FILEMASK[p] & boards[whitePawns])
		){
			bonus=knightOutpostBonus;

			if(PawnAttackBitmap[1] & b){
				bonus+=knightOutpostBonus/2;
				if(!boards[whiteKnights] &&
					!(SQUARE_COLOR_BITMAP[SQUARE_COLOR[p]] &	boards[whiteBishops])){
					bonus+=knightOutpostBonus/2;
				}
			}
			
		}

		res-=makeScore(bonus,bonus);
		//result[0]-=bonus;
		//result[1]-=bonus;

		/*if(!(PawnAttackBitmap[1] & b)){ // unsupported knight
			result[0]+=knightUndefendedOpening;
			result[1]+=knightUndefendedEndgame;
		}
		if((PawnAttackBitmap[0] & b)){ // threath
			result[0]+=knightThreathOpening;
			result[1]+=knightThreathEndgame;
		}*/

		t&=t-1;
	}
	if(trace){
		traceVar[9][0]=mg_value(res)-traceTemp[0];
		traceVar[9][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	// valutazione alfiere
	t=boards[blackBishops];
	while(t){
		//minorpiecesCount++;
		score bonus=0;
		unsigned int p = firstOne(t);
		bitMap b=BITSET[p];

		bitMap attack=BISHOPMOVES(p);
		supportedSquares[1]|=attack;
		occupiedSquares=boards[Board::whitePieces]|boards[Board::blackPawns];
		bitMap pseudoAtt=BISHOPATTACKS(p);
		pseudoAttacks[Board::blackBishops]|=pseudoAtt;
		if(pseudoAtt & kingRing[0]){
			kingAttackersCount[0]++;
			kingAttackersWeight[0]+=2;
			bitMap bb=pseudoAtt & pseudoAttacks[Board::whiteKing];
			if(bb){
				kingAdjacentAttackersCount[0]+=bitCnt(bb);
			}
		}
		occupiedSquares=boards[Board::occupiedSquares];
		int mob;
		if(pinnedPieces & b){
			mob=bitCnt(*SQUARES_BETWEEN_DIRECTION[kingSquare[1]][p] & attack & ~boards[Board::blackPieces] &~PawnAttackBitmap[0]);
		}else{
			mob=bitCnt(attack & ~boards[Board::blackPieces] &~PawnAttackBitmap[0]);
		}
		res -= bishopMobBonus[mob];
		if(mob==0){zeroMobilityBitmap|=BITSET[p];}
		//result[0] -= bishopMobBonusOp[mob];
		//result[1] -= bishopMobBonusEn[mob];

		if((b & outpostMask[1]) && 
			!(PASSED_PAWN[1][p] & ~FILEMASK[p] & boards[whitePawns])
		){
			bonus=bishopOutpostBonus;

			if(PawnAttackBitmap[1] & b){
				bonus+=bishopOutpostBonus/2;
				if(!boards[whiteKnights] &&
					!(SQUARE_COLOR_BITMAP[SQUARE_COLOR[p]] &	boards[whiteBishops])){
					bonus+=bishopOutpostBonus/2;
				}
			}
			
		}

		res -=makeScore(bonus,bonus);
		//result[0]-=bonus;
		//result[1]-=bonus;

		/*if(!(PawnAttackBitmap[1] & b)){ // unsupported bishop
			result[0]+=bishopUndefendedOpening;
			result[1]+=bishopUndefendedEndgame;
		}
		if((PawnAttackBitmap[0] & b)){ // threath
			result[0]+=bishopThreathOpening;
			result[1]+=bishopThreathEndgame;
		}*/

		if(b & SQUARE_COLOR_BITMAP[0]){
			// alfiere su casa chiara
			int n=bitCnt(SQUARE_COLOR_BITMAP[0] & boards[blackPawns])-bitCnt(SQUARE_COLOR_BITMAP[0] & boards[whitePawns]);
			if(n>=2){
				res+=makeScore(badBishopOpening*n,badBishopEndgame*n);
				//result[0]+=badBishopOpening*n;
				//result[1]+=badBishopEndgame*n;
			}
		}
		if(b & SQUARE_COLOR_BITMAP[1]){
			// alfiere su casa chiara
			int n=bitCnt(SQUARE_COLOR_BITMAP[1] & boards[blackPawns])-bitCnt(SQUARE_COLOR_BITMAP[1] & boards[whitePawns]);
			if(n>=2){
				res+=makeScore(badBishopOpening*n,badBishopEndgame*n);
				//result[0]+=badBishopOpening*n;
				//result[1]+=badBishopEndgame*n;
			}
		}

		t&=t-1;
	}
	if(trace){
		traceVar[10][0]=mg_value(res)-traceTemp[0];
		traceVar[10][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	// valutazione torre
	t=boards[blackRooks];
	while(t){
		
		unsigned int p = firstOne(t);
		bitMap b=BITSET[p];
		int rank= RANKS[p];

		bitMap attack=ROOKMOVES(p);
		supportedSquares[1]|=attack;
		occupiedSquares=boards[Board::whitePieces]|boards[Board::blackPawns];
		bitMap pseudoAtt=ROOKATTACKS(p);
		pseudoAttacks[Board::blackRooks]|=pseudoAtt;
		if(pseudoAtt & kingRing[0]){
			kingAttackersCount[0]++;
			kingAttackersWeight[0]+=3;
			bitMap bb=pseudoAtt & pseudoAttacks[Board::whiteKing];
			if(bb){
				kingAdjacentAttackersCount[0]+=bitCnt(bb);
			}
		}
		occupiedSquares=boards[Board::occupiedSquares];
		
		int mob;
		if(pinnedPieces & b){
			mob=bitCnt(*SQUARES_BETWEEN_DIRECTION[kingSquare[1]][p] & attack & ~boards[Board::blackPieces] &~PawnAttackBitmap[0]);
		}else{
			mob=bitCnt(attack & ~boards[Board::blackPieces] &~PawnAttackBitmap[0]);
		}



		res-= rookMobBonus[mob];
		if(mob==0){zeroMobilityBitmap|=BITSET[p];}
		//result[0] -= rookMobBonusOp[mob];
		//result[1] -= rookMobBonusEn[mob];

		/*if(!(PawnAttackBitmap[1] & b)){ // unsupported rook
			result[0]+=rookUndefendedOpening;
			result[1]+=rookUndefendedEndgame;
		}
		if((PawnAttackBitmap[0] & b)){ // threath
			result[0]+=rookThreathOpening;
			result[1]+=rookThreathEndgame;
			
		}*/

		if(rank==1 && (boards[whiteKing]&RANKMASK[H1])){ // torre in 7a con re avversario in 8a
			res-= rookOn7;
			//result[0]-=rookOn7Opening;
			//result[1]-=rookOn7Endgame;
		}
		if(rank<3 && (RANKMASK[p]&boards[whitePawns])){
			res -=rookOnPawn;
			//result[0]-=rookOnPawnOpening;
			//result[1]-=rookOnPawnEndgame;
		}

		// torre su colonna aperta/semiaperta
		if(!(FILEMASK[p]& boards[blackPawns])){
			if(!(FILEMASK[p]& boards[whitePawns])){	// colonna aperta
				res-=rookOnOpen;
				//result[0]-=rookOnOpenOpening;
				//result[1]-=rookOnOpenPawnEndgame;
			}else{
				// colonna semiaperta
				res-=rookOnSemi;
				//result[0]-=rookOnSemiOpening;
				//result[1]-=rookOnSemiPawnEndgame;
			}
		}
		

		t&=t-1;
	}
	if(trace){
		traceVar[11][0]=mg_value(res)-traceTemp[0];
		traceVar[11][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	// valutazione donna
	t=boards[blackQueens];
	while(t){
		
		unsigned int p = firstOne(t);
		bitMap b=BITSET[p];
		int rank= RANKS[p];

		bitMap attack=QUEENMOVES(p);
		supportedSquares[1]|=attack;
		occupiedSquares=boards[Board::whitePieces]|boards[Board::blackPawns];
		bitMap pseudoAtt=(BISHOPATTACKS(p)|ROOKATTACKS(p));
		pseudoAttacks[Board::blackQueens]|=pseudoAtt;
		if(pseudoAtt & kingRing[0]){
			kingAttackersCount[0]++;
			kingAttackersWeight[0]+=5;
			bitMap bb=pseudoAtt & pseudoAttacks[Board::whiteKing];
			if(bb){
				kingAdjacentAttackersCount[0]+=bitCnt(bb);
			}
		}
		occupiedSquares=boards[Board::occupiedSquares];

		int mob;
		if(pinnedPieces & b){
			mob=bitCnt(*SQUARES_BETWEEN_DIRECTION[kingSquare[1]][p] & attack & ~boards[Board::blackPieces] &~PawnAttackBitmap[0]);
		}else{
			mob=bitCnt(attack & ~boards[Board::blackPieces] &~PawnAttackBitmap[0]);
		}
		res-= queenMobBonus[mob];
		if(mob==0){zeroMobilityBitmap|=BITSET[p];}
		//result[0] -= queenMobBonusOp[mob];
		//result[1] -= queenMobBonusEn[mob];
		
		/*if(!(PawnAttackBitmap[1] & b)){ // unsupported rook
			result[0]+=queenUndefendedOpening;
			result[1]+=queenUndefendedEndgame;
		}
		if((PawnAttackBitmap[0] & b)){ // threath
			result[0]+=queenThreathOpening;
			result[1]+=queenThreathEndgame;
		}*/
		
		if(rank==1 && (boards[whiteKing]&RANKMASK[H1])){ // donna in 7a con re avversario in 8a
			res -= queenOn7;
			//result[0]-=queenOn7Opening;
			//result[1]-=queenOn7Endgame;
		}
		
		if(rank<3 && (RANKMASK[p]&boards[whitePawns])){
			res -= queenOnPawn;
			//result[0]-=queenOnPawnOpening;
			//result[1]-=queenOnPawnEndgame;
		}

		t&=t-1;
	}
	if(trace){
		traceVar[12][0]=mg_value(res)-traceTemp[0];
		traceVar[12][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	//controllo del centro
	int centerControl=(bitCnt(pseudoAttacks[Board::whiteBishops]&littleCenter)-bitCnt(pseudoAttacks[Board::blackBishops]&littleCenter))*littleCenterControlOpening
	+(bitCnt(pseudoAttacks[Board::whiteKnights]&littleCenter)-bitCnt(pseudoAttacks[Board::blackKnights]&littleCenter))*littleCenterControlOpening
	+(bitCnt(pseudoAttacks[Board::whiteRooks]&littleCenter)-bitCnt(pseudoAttacks[Board::blackRooks]&littleCenter))*littleCenterControlOpening
	+(bitCnt(pseudoAttacks[Board::whiteQueens]&littleCenter)-bitCnt(pseudoAttacks[Board::blackQueens]&littleCenter))*littleCenterControlOpening
	+(bitCnt(pseudoAttacks[Board::whiteBishops]&bigCenter)-bitCnt(pseudoAttacks[Board::blackBishops]&bigCenter))*bigCenterControlOpening
	+(bitCnt(pseudoAttacks[Board::whiteKnights]&bigCenter)-bitCnt(pseudoAttacks[Board::blackKnights]&bigCenter))*bigCenterControlOpening
	+(bitCnt(pseudoAttacks[Board::whiteRooks]&bigCenter)-bitCnt(pseudoAttacks[Board::blackRooks]&bigCenter))*bigCenterControlOpening
	+(bitCnt(pseudoAttacks[Board::whiteQueens]&bigCenter)-bitCnt(pseudoAttacks[Board::blackQueens]&bigCenter))*bigCenterControlOpening;
	
	//result[0]+=(bitCnt(pseudoAttacks[Board::whiteBishops]&littleCenter)-bitCnt(pseudoAttacks[Board::blackBishops]&littleCenter))*littleCenterControlOpening;
	//result[0]+=(bitCnt(pseudoAttacks[Board::whiteKnights]&littleCenter)-bitCnt(pseudoAttacks[Board::blackKnights]&littleCenter))*littleCenterControlOpening;
	//result[0]+=(bitCnt(pseudoAttacks[Board::whiteRooks]&littleCenter)-bitCnt(pseudoAttacks[Board::blackRooks]&littleCenter))*littleCenterControlOpening;
	//result[0]+=(bitCnt(pseudoAttacks[Board::whiteQueens]&littleCenter)-bitCnt(pseudoAttacks[Board::blackQueens]&littleCenter))*littleCenterControlOpening;

	//result[0]+=(bitCnt(pseudoAttacks[Board::whiteBishops]&bigCenter)-bitCnt(pseudoAttacks[Board::blackBishops]&bigCenter))*bigCenterControlOpening;
	//result[0]+=(bitCnt(pseudoAttacks[Board::whiteKnights]&bigCenter)-bitCnt(pseudoAttacks[Board::blackKnights]&bigCenter))*bigCenterControlOpening;
	//result[0]+=(bitCnt(pseudoAttacks[Board::whiteRooks]&bigCenter)-bitCnt(pseudoAttacks[Board::blackRooks]&bigCenter))*bigCenterControlOpening;
	//result[0]+=(bitCnt(pseudoAttacks[Board::whiteQueens]&bigCenter)-bitCnt(pseudoAttacks[Board::blackQueens]&bigCenter))*bigCenterControlOpening;
	res += makeScore(centerControl,0);
	if(trace){
		traceVar[13][0]=mg_value(res)-traceTemp[0];
		traceVar[13][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	bitMap attackedSquares[2];
	attackedSquares[0]=pseudoAttacks[Board::whiteKing]|
			pseudoAttacks[Board::whitePawns]|
			pseudoAttacks[Board::whiteBishops]|
			pseudoAttacks[Board::whiteKnights]|
			pseudoAttacks[Board::whiteRooks]|
			pseudoAttacks[Board::whiteQueens];
	attackedSquares[1]=pseudoAttacks[Board::blackKing]|
			pseudoAttacks[Board::blackPawns]|
			pseudoAttacks[Board::blackBishops]|
			pseudoAttacks[Board::blackKnights]|
			pseudoAttacks[Board::blackRooks]|
			pseudoAttacks[Board::blackQueens];
	/*******************************************************
	* SPACE
	*********************************************************/
	bitMap safe =  spaceMask[0]											// maschera di bit
					& ~boards[whitePawns]								// dove non ci sono nostri pedoni
					& ~PawnAttackBitmap[1]								// non attaccata dai loro pedoni
					& (attackedSquares[0] | ~attackedSquares[1]);		// attaccata da noi o non attaccata da loro
	
	//displayBitmap(safe);
	bitMap behind = boards[whitePawns];
	behind |= behind >>  8;
	behind |= behind >> 16;

	//displayBitmap(safe & behind);
	int spaceCount=bitCnt(safe)+bitCnt(safe& behind);

	safe =  spaceMask[1]											// maschera di bit
					& ~boards[blackPawns]								// dove non ci sono nostri pedoni
					& ~PawnAttackBitmap[0]								// non attaccata da loro pedoni
					& (attackedSquares[1] | ~attackedSquares[0]);		// attaccata da noi o non attaccata da loro

	//displayBitmap(safe);
	behind = boards[blackPawns];
	behind |= behind <<  8;
	behind |= behind << 16;

	//displayBitmap(safe& behind);
	spaceCount-=bitCnt(safe)+bitCnt(safe& behind);

	minorpiecesCount=pieceCount[whiteKnights]+pieceCount[whiteBishops]+pieceCount[blackKnights]+pieceCount[blackBishops];
	score sw=(spaceWeight*minorpiecesCount*minorpiecesCount);

	res+=makeScore((score)(spaceCount*sw)/512,0);
	//result[Board::opening]+=(score)(spaceCount*sw)/512;
	//std::cout<<spaceCount<<std::endl;

	if(trace){
			traceVar[14][0]=mg_value(res)-traceTemp[0];
			traceVar[14][1]=eg_value(res)-traceTemp[1];
			traceTemp[0]=mg_value(res);
			traceTemp[1]=eg_value(res);
		}


	//counterAttack
	signed int gp=getGamePhase();
	int counterAttackWgain=128,counterAttackBgain=128;
	if(Material<-900){ // nero vince, bianco cerca di attaccare il re nero
		counterAttackWgain=140;
	}
	if(Material>900){ //bianco vince, nero cerca di contrattaccare il re nero
		counterAttackBgain=140;
	}

	/*display();
	displayBitmap(supportedSquares[0]);
	displayBitmap(supportedSquares[1]);

	displayBitmap(pseudoAttacks[Board::whiteKnights]|pseudoAttacks[Board::whiteBishops]| pseudoAttacks[Board::whiteRooks] | pseudoAttacks[Board::whiteQueens] |pseudoAttacks[Board::whiteKing] |pseudoAttacks[Board::whitePawns]);
	displayBitmap(pseudoAttacks[Board::blackKnights]|pseudoAttacks[Board::blackBishops]| pseudoAttacks[Board::blackRooks] | pseudoAttacks[Board::blackQueens] |pseudoAttacks[Board::blackKing] |pseudoAttacks[Board::blackPawns]);
	*/


	bitMap weak=weakPawns & boards[Board::whitePawns] & supportedSquares[1];
	if(weak){
		unsigned int cnt=bitCnt(weak)*6;
		res-=makeScore(cnt,cnt);
		//result[0]-=cnt;
		//result[1]-=cnt;
	}
	weak=weakPawns & boards[Board::blackPawns] & supportedSquares[0];
	if(weak){
		unsigned int cnt=bitCnt(weak)*6;
		res+=makeScore(cnt,cnt);
		//result[0]+=cnt;
		//result[1]+=cnt;
	}
	/************************************************
	* UNSUPPORTED PIECES
	************************************************/
	// unsupported minor pieces

	bitMap undefendedMinors =(boards[Board::whiteBishops]|boards[Board::whiteKnights]) & ~supportedSquares[0];
	if(undefendedMinors){

		res-=undefendedMinorPenalty;
		//result[0]-=undefendedMinorPenaltyOpening;
		//result[1]-=undefendedMinorPenaltyEndgame;
		if(bitCnt(undefendedMinors)>1){
			res-=undefendedMinorPenalty;
			//result[0]-=undefendedMinorPenaltyOpening;
			//result[1]-=undefendedMinorPenaltyEndgame;

		}
	}

	bitMap weakPieces= boards[Board::whitePieces] & ~supportedSquares[0] & supportedSquares[1];
	if(weakPieces){
		if(zeroMobilityBitmap & weakPieces){
			res-=makeScore(100,100);
		}
		while(weakPieces){
			unsigned int p = firstOne(weakPieces);
			res-=threatPenalty[square[p]%Board::emptyBitmap];
			//result[0]-=threatPenaltyOpening[square[p]%Board::emptyBitmap];
			//result[1]-=threatPenaltyEndgame[square[p]%Board::emptyBitmap];
			weakPieces&=weakPieces-1;
		}
	}

	if(trace){
		traceVar[15][0]=mg_value(res)-traceTemp[0];
		traceVar[15][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}

	undefendedMinors =(boards[Board::blackBishops]|boards[Board::blackKnights]) & ~supportedSquares[1];
	if(undefendedMinors){
		res+=undefendedMinorPenalty;
		//result[0]+=undefendedMinorPenaltyOpening;
		//result[1]+=undefendedMinorPenaltyEndgame;
		if(bitCnt(undefendedMinors)>1){
			res+=undefendedMinorPenalty;
			//result[0]+=undefendedMinorPenaltyOpening;
			//result[1]+=undefendedMinorPenaltyEndgame;

		}
	}


	weakPieces= boards[Board::blackPieces] & ~supportedSquares[1] & supportedSquares[0];
	if(weakPieces){
		if(zeroMobilityBitmap & weakPieces){
			res+=makeScore(100,100);
		}
		while(weakPieces){
			unsigned int p = firstOne(weakPieces);
			res+=threatPenalty[square[p]%Board::emptyBitmap];
			//result[0]+=threatPenaltyOpening[square[p]%Board::emptyBitmap];
			//result[1]+=threatPenaltyEndgame[square[p]%Board::emptyBitmap];
			weakPieces&=weakPieces-1;
		}
	}
	if(trace){
		traceVar[16][0]=mg_value(res)-traceTemp[0];
		traceVar[16][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}
	//-----------------------------------------------

	


	t=boards[whiteKing];
	//***************KING SHIELD/STORM****************
	{
		unsigned int p = firstOne(t);
		int sh;
		{
			
		int d=bitCnt(PAWNKINGSHIELD[0][0][p]& boards[whitePawns]);
		int a=bitCnt(PAWNKINGSHIELD[0][0][p]& boards[blackPawns]);
		int df=bitCnt(PAWNKINGSHIELD[1][0][p]& boards[whitePawns]);
		int af=bitCnt(PAWNKINGSHIELD[1][0][p]& boards[blackPawns]);
		sh=d*kingShieldBonus[0]+df*kingShieldBonus[1]+a*kingShieldBonus[2]+af*kingShieldBonus[3];
		}
		if((castleRights & wCastleOO) && (boards[Board::occupiedSquares]& MASKFG[0])==0 && (supportedSquares[1]& MASKFG[0])==0){
			int d=bitCnt(PAWNKINGSHIELD[0][0][G1]& boards[whitePawns]);
			int a=bitCnt(PAWNKINGSHIELD[0][0][G1]& boards[blackPawns]);
			int df=bitCnt(PAWNKINGSHIELD[1][0][G1]& boards[whitePawns]);
			int af=bitCnt(PAWNKINGSHIELD[1][0][G1]& boards[blackPawns]);
			int res00=d*kingShieldBonus[0]+df*kingShieldBonus[1]+a*kingShieldBonus[2]+af*kingShieldBonus[3];
			sh=(std::max)(sh,res00);
		}
		if((castleRights & wCastleOOO) && (boards[Board::occupiedSquares]& MASKBD[0])==0 && (supportedSquares[1]& MASKBD[0])==0){
			int d=bitCnt(PAWNKINGSHIELD[0][0][C1]& boards[whitePawns]);
			int a=bitCnt(PAWNKINGSHIELD[0][0][C1]& boards[blackPawns]);
			int df=bitCnt(PAWNKINGSHIELD[1][0][C1]& boards[whitePawns]);
			int af=bitCnt(PAWNKINGSHIELD[1][0][C1]& boards[blackPawns]);
			int res000=d*kingShieldBonus[0]+df*kingShieldBonus[1]+a*kingShieldBonus[2]+af*kingShieldBonus[3];
			sh=(std::max)(sh,res000);

		}
		res+=makeScore(sh,0);
	}
	if(trace){
		traceVar[17][0]=mg_value(res)-traceTemp[0];
		traceVar[17][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	t=boards[blackKing];
	//***************KING SHIELD/STORM****************
	{
		unsigned int p = firstOne(t);
		int sh;
		{
		int d=bitCnt(PAWNKINGSHIELD[0][1][p]& boards[blackPawns]);
		int a=bitCnt(PAWNKINGSHIELD[0][1][p]& boards[whitePawns]);
		int df=bitCnt(PAWNKINGSHIELD[1][1][p]& boards[blackPawns]);
		int af=bitCnt(PAWNKINGSHIELD[1][1][p]& boards[whitePawns]);
		sh=d*kingShieldBonus[0]+df*kingShieldBonus[1]+a*kingShieldBonus[2]+af*kingShieldBonus[3];
		}
		if((castleRights & bCastleOO) && (boards[Board::occupiedSquares]& MASKFG[1])==0 && (supportedSquares[0]& MASKFG[1])==0){
			int d=bitCnt(PAWNKINGSHIELD[0][1][G8]& boards[blackPawns]);
			int a=bitCnt(PAWNKINGSHIELD[0][1][G8]& boards[whitePawns]);
			int df=bitCnt(PAWNKINGSHIELD[1][1][G8]& boards[blackPawns]);
			int af=bitCnt(PAWNKINGSHIELD[1][1][G8]& boards[whitePawns]);
			int res00=d*kingShieldBonus[0]+df*kingShieldBonus[1]+a*kingShieldBonus[2]+af*kingShieldBonus[3];
			sh=(std::max)(sh,res00);
		}
		if((castleRights & bCastleOOO) && (boards[Board::occupiedSquares]& MASKBD[1])==0 && (supportedSquares[0]& MASKBD[1])==0){
			int d=bitCnt(PAWNKINGSHIELD[0][1][C8]& boards[blackPawns]);
			int a=bitCnt(PAWNKINGSHIELD[0][1][C8]& boards[whitePawns]);
			int df=bitCnt(PAWNKINGSHIELD[1][1][C8]& boards[blackPawns]);
			int af=bitCnt(PAWNKINGSHIELD[1][1][C8]& boards[whitePawns]);
			int res000=d*kingShieldBonus[0]+df*kingShieldBonus[1]+a*kingShieldBonus[2]+af*kingShieldBonus[3];
			sh=(std::max)(sh,res000);

		}
		res-=makeScore(sh,0);
	}
	if(trace){
		traceVar[18][0]=mg_value(res)-traceTemp[0];
		traceVar[18][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}



	
	

#ifdef _KING_SAFETY_DEBUG
	display();
	std::cout<<"------white king-------------"<<std::endl;
#endif

	if(kingAttackersCount[0]>=2 && kingAdjacentAttackersCount[0]){
		
		bitMap undefended= 
			(attackedSquares[1]) & pseudoAttacks[Board::whiteKing];
		undefended &= ~(pseudoAttacks[Board::whitePawns]|
			pseudoAttacks[Board::whiteBishops]|
			pseudoAttacks[Board::whiteKnights]|
			pseudoAttacks[Board::whiteRooks]|
			pseudoAttacks[Board::whiteQueens]);
		
		
		int attackUnits =  ((kingAttackersCount[0] * kingAttackersWeight[0]*counterAttackBgain/128) / 2) + 3 * (kingAdjacentAttackersCount[0] + bitCnt(undefended));
		if(attackUnits>=100){
			attackUnits=99;
		}
		res-=kingSafetyEval[attackUnits];
		

		
	}
	if(trace){
		traceVar[19][0]=mg_value(res)-traceTemp[0];
		traceVar[19][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}
	
	if(kingAttackersCount[1]>=2 && kingAdjacentAttackersCount[1]){
		
		bitMap undefended= 
			(attackedSquares[0]) & pseudoAttacks[Board::blackKing];
		undefended &= ~(pseudoAttacks[Board::blackPawns]|
			pseudoAttacks[Board::blackBishops]|
			pseudoAttacks[Board::blackKnights]|
			pseudoAttacks[Board::blackRooks]|
			pseudoAttacks[Board::blackQueens]);
		
		
		int attackUnits =  ((kingAttackersCount[1] * kingAttackersWeight[1]*counterAttackWgain/128) / 2) + 3 * (kingAdjacentAttackersCount[1] + bitCnt(undefended));
		if(attackUnits>=100){
			attackUnits=99;
		}
		res+=kingSafetyEval[attackUnits];
		

		
	}
	if(trace){
		traceVar[20][0]=mg_value(res)-traceTemp[0];
		traceVar[20][1]=eg_value(res)-traceTemp[1];
		traceTemp[0]=mg_value(res);
		traceTemp[1]=eg_value(res);
	}

	score result[2];
	result[0]=mg_value(res);
	result[1]=eg_value(res);
	/*******************************************************
	 * scale result in the endgame if it looks drawish
	 *
	 *******************************************************/


	if(abs(result[1])<VALUE_KNOWN_WIN){
		bitMap blockedPawn= (boards[Board::whitePawns]<<8)&boards[Board::blackPawns];
		unsigned int blockedPawns=bitCnt(blockedPawn);

		result[1]=((int)result[1]*blockedPawnsScaling[blockedPawns])/64;
	}

	/*******************************************************
	* finalize evalutation
	*
	********************************************************/

	if(trace){
		printTrace();
	}
	eval=(result[Board::opening]*(128-gp)+result[Board::endgame]*(gp))/128;
	if(nextMove){
		eval= -eval;
	}


	if(trace){
		std::cout<<"gamePhase: "<<gp/128.0*100<<std::endl;
		std::cout<<"eval: "<<eval/3<<std::endl;
	}
	return eval;
}





template score Board::eval<true>();
template score Board::eval<false>();


void Board::initPST(){

	static const score pawnPSTopening[] =
	{
		  0,   0,   0,   0,   0,   0,   0,   0,
		-36,  -18,   0,  18,  18,   0,  -18, -36,
		-36,  -18,   0,  18,  18,   0,  -18, -36,
		-36,  -18,   0,  48,  48,   0,  -18, -36,
		-36,  -18,   0,  78,  78,   0,  -18, -36,
		-36,  -18,   0,  48,  48,   0,  -18, -36,
		-36,  -18,   0,  18,  18,   0,  -18, -36,
		  0,   0,   0,   0,   0,   0,   0,   0
	};
	static const score pawnPSTendgame[] =
	{
		  0,   0,   0,   0,   0,   0,   0,   0,
		-36,  -18,   0,   18,   18,   0,  -18, -36,
		-36,  -18,   0,   18,   18,   0,  -18, -36,
		-36,  -18,   0,   18,   18,   0,  -18, -36,
		-36,  -18,   0,   18,   18,   0,  -18, -36,
		-36,  -18,   0,   18,   18,   0,  -18, -36,
		-36,  -18,   0,   18,   18,   0,  -18, -36,
		  0,   0,   0,   0,   0,   0,   0,   0
	};

	// knight
	static const score knightPSTopening[] =
	{
		-90, -60, -60, -30, -30, -60, -60, -90,
		-15, +21, +36, +45, +45, +36, +21, -15,
		-15, +30, +60, +75, +75, +60, +30, -15,
		-15, +36, +45, +90, +90, +45, +36, -15,
		-15, +30, +60, +75, +75, +60, +30, -15,
		-15, +00, +45, +30, +30, +45, +00, -15,
		-15, +00, +00, +00, +00, +00, +00, -15,
		-90, -60, -60, -30, -30, -60, -60, -90
	};

	static const score knightPSTendgame[] =
	{
		-90, -60, -60, -30, -30, -60, -60, -90,
		-15, +21, +36, +45, +45, +36, +21, -15,
		-15, +30, +60, +75, +75, +60, +30, -15,
		-15, +36, +45, +90, +90, +45, +36, -15,
		-15, +30, +60, +75, +75, +60, +30, -15,
		-15, +00, +45, +30, +30, +45, +00, -15,
		-15, +00, +00, +00, +00, +00, +00, -15,
		-90, -60, -60, -30, -30, -60, -60, -90
	};

	// bishop
	static const score bishopPSTopening[] =
	{
		-45, -45, -21, -12, -12, -21, -45, -45,
		-30, -15, -15, +00, +00, -15, -15, -30,
		-15, -9, +18, +12, +12, +18, -9, -15,
		-9, +00, +12, +30, +30, +12, +00, -9,
		-9, +00, +12, +30, +30, +12, +00, -9,
		-15, -9, +18, +12, +12, +18, -9, -15,
		-30, +00, -15, +00, +00, -15, +00, -30,
		-60, -60, -60, -30, -30, -60, -60, -60
	};

	static const score bishopPSTendgame[] =
	{
		-90, -60, -30, -30, -30, -30, -60, -90,
		-60, -30, +00, +00, +00, +00, -30, -60,
		-30, +00, +06, +12, +12, +06, +00, -30,
		-30, +00, +12, +21, +21, +12, +00, -30,
		-30, +00, +12, +21, +21, +12, +00, -30,
		-30, +00, +06, +12, +12, +06, +00, -30,
		-60, -30, +00, +00, +00, +00, -30, -60,
		-90, -60, -30, -30, -30, -30, -60, -90
	};

	// rook
	static const score rookPSTopening[] =
	{
		-15, -06, +00, +15, +15, +00, -06, -15,
		-15, -06, +00, +15, +15, +00, -06, -15,
		-15, -06, +00, +15, +15, +00, -06, -15,
		-15, -06, +00, +15, +15, +00, -06, -15,
		-15, -06, +00, +15, +15, +00, -06, -15,
		-15, -06, +00, +15, +15, +00, -06, -15,
		-15, -06, +00, +15, +15, +00, -06, -15,
		-15, -06, +00, +15, +15, +00, -06, -15
	};

	static const score rookPSTendgame[] =
	{
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00
	};

	// queen
	static const score queenPSTopening[] =
	{
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00
	};


	static const score queenPSTendgame[] =
	{
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00
	};

	// king
	static const score kingPSTopening[] =
	{
		-150, -150, -150, -150, -150, -150, -150, -150,
		-150, -150, -150, -150, -150, -150, -150, -150,
		-150, -150, -150, -150, -150, -150, -150, -150,
		-150, -150, -150, -150, -150, -150, -150, -150,
		-150, -150, -150, -150, -150, -150, -150, -150,
		-90, -90, -90, -90, -90, -90, -90, -90,
		+30, +30, +00, -30, -30, +00, +30, +30,
		+60, +120, +15, +00, +00, +15, +120, +60
	};

	static const score kingPSTendgame[] =
	{
		-30, +00, +00, +00, +00, +00, +00, -30,
		+00, +00, +00, +00, +00, +00, +00, +00,
		+00, +00, +30, +90, +90, +30, +00, +00,
		+00, +00, +90, +120, +120, +90, +00, +00,
		+00, +00, +90, +120, +120, +90, +00, +00,
		+00, +00, +30, +90, +90, +30, +00, +00,
		+00, +00, +00, +00, +00, +00, +00, +00,
		-30, +00, +00, +00, +00, +00, +00, -30
	};




	for(int sq=0;sq<64;sq++){
		for(int i=0;i<lastBitboard;i++){
			PST[i][sq]=0;
			PST[i][sq]=0;
		}
	}

	for(int sq=0;sq<64;sq++){
		PST[whitePawns][sq]=makeScore(pawnPSTopening[whiteIndex[sq]]+pawnEndgameBonusPst,pawnPSTendgame[whiteIndex[sq]]);
		PST[blackPawns][sq]=makeScore(-pawnPSTopening[blackIndex[sq]]-pawnEndgameBonusPst,-pawnPSTendgame[blackIndex[sq]]);

		PST[whiteKnights][sq]=makeScore(knightPSTopening[whiteIndex[sq]],knightPSTendgame[whiteIndex[sq]]);
		PST[blackKnights][sq]=makeScore(-knightPSTopening[blackIndex[sq]],-knightPSTendgame[blackIndex[sq]]);

		PST[whiteBishops][sq]=makeScore(bishopPSTopening[whiteIndex[sq]],bishopPSTendgame[whiteIndex[sq]]);
		PST[blackBishops][sq]=makeScore(-bishopPSTopening[blackIndex[sq]],-bishopPSTendgame[blackIndex[sq]]);

		PST[whiteRooks][sq]=makeScore(rookPSTopening[whiteIndex[sq]],rookPSTendgame[whiteIndex[sq]]);
		PST[blackRooks][sq]=makeScore(-rookPSTopening[blackIndex[sq]],-rookPSTendgame[blackIndex[sq]]);

		PST[whiteQueens][sq]=makeScore(queenPSTopening[whiteIndex[sq]],queenPSTendgame[whiteIndex[sq]]);
		PST[blackQueens][sq]=makeScore(-queenPSTopening[blackIndex[sq]],-queenPSTendgame[blackIndex[sq]]);

		PST[whiteKing][sq]=makeScore(kingPSTopening[whiteIndex[sq]],kingPSTendgame[whiteIndex[sq]]);
		PST[blackKing][sq]=makeScore(-kingPSTopening[blackIndex[sq]],-kingPSTendgame[blackIndex[sq]]);
		
	}
	materialKBNvsk=  Board::KEY.keys[1][Board::whiteKing]
					^Board::KEY.keys[0][Board::whiteQueens]
					^Board::KEY.keys[0][Board::whiteRooks]
					^Board::KEY.keys[1][Board::whiteBishops]
					^Board::KEY.keys[1][Board::whiteKnights]
					^Board::KEY.keys[0][Board::whitePawns]
					^Board::KEY.keys[1][Board::blackKing]
					^Board::KEY.keys[0][Board::blackQueens]
					^Board::KEY.keys[0][Board::blackRooks]
					^Board::KEY.keys[0][Board::blackBishops]
					^Board::KEY.keys[0][Board::blackKnights]
					^Board::KEY.keys[0][Board::blackPawns];
	materialKvskBN=  Board::KEY.keys[1][Board::whiteKing]
					^Board::KEY.keys[0][Board::whiteQueens]
					^Board::KEY.keys[0][Board::whiteRooks]
					^Board::KEY.keys[0][Board::whiteBishops]
					^Board::KEY.keys[0][Board::whiteKnights]
					^Board::KEY.keys[0][Board::whitePawns]
					^Board::KEY.keys[1][Board::blackKing]
					^Board::KEY.keys[0][Board::blackQueens]
					^Board::KEY.keys[0][Board::blackRooks]
					^Board::KEY.keys[1][Board::blackBishops]
					^Board::KEY.keys[1][Board::blackKnights]
					^Board::KEY.keys[0][Board::blackPawns];

	materialKPvsk=   Board::KEY.keys[1][Board::whiteKing]
					^Board::KEY.keys[0][Board::whiteQueens]
					^Board::KEY.keys[0][Board::whiteRooks]
					^Board::KEY.keys[0][Board::whiteBishops]
					^Board::KEY.keys[0][Board::whiteKnights]
					^Board::KEY.keys[1][Board::whitePawns]
					^Board::KEY.keys[1][Board::blackKing]
					^Board::KEY.keys[0][Board::blackQueens]
					^Board::KEY.keys[0][Board::blackRooks]
					^Board::KEY.keys[0][Board::blackBishops]
					^Board::KEY.keys[0][Board::blackKnights]
					^Board::KEY.keys[0][Board::blackPawns];

	materialKvskp=   Board::KEY.keys[1][Board::whiteKing]
					^Board::KEY.keys[0][Board::whiteQueens]
					^Board::KEY.keys[0][Board::whiteRooks]
					^Board::KEY.keys[0][Board::whiteBishops]
					^Board::KEY.keys[0][Board::whiteKnights]
					^Board::KEY.keys[0][Board::whitePawns]
					^Board::KEY.keys[1][Board::blackKing]
					^Board::KEY.keys[0][Board::blackQueens]
					^Board::KEY.keys[0][Board::blackRooks]
					^Board::KEY.keys[0][Board::blackBishops]
					^Board::KEY.keys[0][Board::blackKnights]
					^Board::KEY.keys[1][Board::blackPawns];

	materialKPvskn=  Board::KEY.keys[1][Board::whiteKing]
					^Board::KEY.keys[0][Board::whiteQueens]
					^Board::KEY.keys[0][Board::whiteRooks]
					^Board::KEY.keys[0][Board::whiteBishops]
					^Board::KEY.keys[0][Board::whiteKnights]
					^Board::KEY.keys[1][Board::whitePawns]
					^Board::KEY.keys[1][Board::blackKing]
					^Board::KEY.keys[0][Board::blackQueens]
					^Board::KEY.keys[0][Board::blackRooks]
					^Board::KEY.keys[0][Board::blackBishops]
					^Board::KEY.keys[1][Board::blackKnights]
					^Board::KEY.keys[0][Board::blackPawns];

	materialKPvskb=  Board::KEY.keys[1][Board::whiteKing]
					^Board::KEY.keys[0][Board::whiteQueens]
					^Board::KEY.keys[0][Board::whiteRooks]
					^Board::KEY.keys[0][Board::whiteBishops]
					^Board::KEY.keys[0][Board::whiteKnights]
					^Board::KEY.keys[1][Board::whitePawns]
					^Board::KEY.keys[1][Board::blackKing]
					^Board::KEY.keys[0][Board::blackQueens]
					^Board::KEY.keys[0][Board::blackRooks]
					^Board::KEY.keys[1][Board::blackBishops]
					^Board::KEY.keys[0][Board::blackKnights]
					^Board::KEY.keys[0][Board::blackPawns];

	materialKNvskp=  Board::KEY.keys[1][Board::whiteKing]
					^Board::KEY.keys[0][Board::whiteQueens]
					^Board::KEY.keys[0][Board::whiteRooks]
					^Board::KEY.keys[0][Board::whiteBishops]
					^Board::KEY.keys[1][Board::whiteKnights]
					^Board::KEY.keys[0][Board::whitePawns]
					^Board::KEY.keys[1][Board::blackKing]
					^Board::KEY.keys[0][Board::blackQueens]
					^Board::KEY.keys[0][Board::blackRooks]
					^Board::KEY.keys[0][Board::blackBishops]
					^Board::KEY.keys[0][Board::blackKnights]
					^Board::KEY.keys[1][Board::blackPawns];

	materialKBvskp=  Board::KEY.keys[1][Board::whiteKing]
					^Board::KEY.keys[0][Board::whiteQueens]
					^Board::KEY.keys[0][Board::whiteRooks]
					^Board::KEY.keys[1][Board::whiteBishops]
					^Board::KEY.keys[0][Board::whiteKnights]
					^Board::KEY.keys[0][Board::whitePawns]
					^Board::KEY.keys[1][Board::blackKing]
					^Board::KEY.keys[0][Board::blackQueens]
					^Board::KEY.keys[0][Board::blackRooks]
					^Board::KEY.keys[0][Board::blackBishops]
					^Board::KEY.keys[0][Board::blackKnights]
					^Board::KEY.keys[1][Board::blackPawns];

/*	for(int i=0;i<32;i++){
		knightMobBonusOp[i]=(int)(knightMobOpA*i*i+knightMobOpM*i+knightMobOpQ);
	}
	knightMobBonusOp[0]=(int)knightMobOp0;

	for(int i=0;i<32;i++){
		knightMobBonusEn[i]=(int)(knightMobEnA*i*i+knightMobEnM*i+knightMobEnQ);
	}
	knightMobBonusEn[0]=(int)knightMobEn0;
*/
	for(int i=0;i<32;i++){
		knightMobBonus[i]=makeScore((int)(knightMobOpA*i*i+knightMobOpM*i+knightMobOpQ),(int)(knightMobEnA*i*i+knightMobEnM*i+knightMobEnQ));
	}
	//knightMobBonus[0]=makeScore((int)knightMobOp0,(int)knightMobEn0);


/*	for(int i=0;i<32;i++){
		bishopMobBonusOp[i]=(int)(bishopMobOpA*i*i+bishopMobOpM*i+bishopMobOpQ);
	}
	bishopMobBonusOp[0]=(int)bishopMobOp0;

	for(int i=0;i<32;i++){
		bishopMobBonusEn[i]=(int)(bishopMobEnA*i*i+bishopMobEnM*i+bishopMobEnQ);
	}
	bishopMobBonusEn[0]=(int)bishopMobEn0;

*/	for(int i=0;i<32;i++){
		bishopMobBonus[i]=makeScore((int)(bishopMobOpA*i*i+bishopMobOpM*i+bishopMobOpQ),(int)(bishopMobEnA*i*i+bishopMobEnM*i+bishopMobEnQ));
	}
	//bishopMobBonus[0]=makeScore((int)bishopMobOp0,(int)bishopMobEn0);



/*	for(int i=0;i<32;i++){
		rookMobBonusOp[i]=(int)(rookMobOpA*i*i+rookMobOpM*i+rookMobOpQ);
	}
	rookMobBonusOp[0]=(int)rookMobOp0;

	for(int i=0;i<32;i++){
		rookMobBonusEn[i]=(int)(rookMobEnA*i*i+rookMobEnM*i+rookMobEnQ);
	}
	rookMobBonusEn[0]=(int)rookMobEn0;
*/
	for(int i=0;i<32;i++){
		rookMobBonus[i]=makeScore((int)(rookMobOpA*i*i+rookMobOpM*i+rookMobOpQ),(int)(rookMobEnA*i*i+rookMobEnM*i+rookMobEnQ));
	}
	//rookMobBonus[0]=makeScore((int)rookMobOp0,(int)rookMobEn0);

/*	for(int i=0;i<32;i++){
		queenMobBonusOp[i]=(int)(queenMobOpA*i*i+queenMobOpM*i+queenMobOpQ);
	}
	queenMobBonusOp[0]=(int)queenMobOp0;

	for(int i=0;i<32;i++){
		queenMobBonusEn[i]=(int)(queenMobEnA*i*i+queenMobEnM*i+queenMobEnQ);
	}
	queenMobBonusEn[0]=(int)queenMobEn0;

*/	for(int i=0;i<32;i++){
		queenMobBonus[i]=makeScore((int)(queenMobOpA*i*i+queenMobOpM*i+queenMobOpQ),(int)(queenMobEnA*i*i+queenMobEnM*i+queenMobEnQ));
	}
	//queenMobBonus[0]=makeScore((int)queenMobOp0,(int)queenMobEn0);

	for(int ppp=0;ppp<100;ppp++){
		float f1=kingSafety0;
		float f2=kingSafety1/100.0;
		float f3=kingSafety2/1000.0;
		kingSafetyEval[ppp]=makeScore((score)(f1+f2*ppp+f3*ppp*ppp),(score)(f1+f2*ppp+f3*ppp*ppp)*0.5);
		//std::cout<<kingSafetyEval[ppp]<<std::endl;
	}

	for(int i=0;i<8;i++){
		isolatedPawnPenalty[0][i]=makeScore(isolatedPawnPenaltyOpening[0][i], isolatedPawnPenaltyEndgame[0][i]);
		isolatedPawnPenalty[1][i]=makeScore(isolatedPawnPenaltyOpening[1][i], isolatedPawnPenaltyEndgame[1][i]);
		isolatedPawnHalfPenalty[0][i]=makeScore(isolatedPawnPenaltyOpening[0][i]/2, isolatedPawnPenaltyEndgame[0][i]/2);
		isolatedPawnHalfPenalty[1][i]=makeScore(isolatedPawnPenaltyOpening[1][i]/2, isolatedPawnPenaltyEndgame[1][i]/2);
		chainedPawnBonus[i]=makeScore(chainedPawnBonusOpening[i], chainedPawnBonusEndgame[i]);
		backwardPawnPenalty[i]=makeScore(backwardPawnPenaltyOpening[i], backwardPawnPenaltyEndgame[i]);
	}
	doubledPawnPenalty[0]=makeScore(doubledPawnPenaltyOpening[0], doubledPawnPenaltyEndgame[0]);
	doubledPawnPenalty[1]=makeScore(doubledPawnPenaltyOpening[1], doubledPawnPenaltyEndgame[1]);
	passedPawnBonus=makeScore(passedPawnBonusOpening, passedPawnBonusEndgame);

}
